Coverage Report

Created: 2026-09-13 06:13

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.2k
#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
961k
{
71
961k
  return c == ' '
72
757k
      || c == '\t'
73
732k
      || c == '\n'
74
729k
      || c == '\r';
75
961k
}
76
77
static inline int is_hex_char(char c)
78
11.2k
{
79
11.2k
  return (c >= '0' && c <= '9')
80
3.65k
      || (c >= 'A' && c <= 'F')
81
354
      || (c >= 'a' && c <= 'f');
82
11.2k
}
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
384
{
134
384
  int jerr_int = (int)jerr;
135
384
  if (jerr_int < 0 ||
136
384
      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
384
  return json_tokener_errors[jerr];
140
384
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
768
{
144
768
  return tok->err;
145
768
}
146
147
/* Stuff for decoding unicode sequences */
148
1.77k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.50k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
295
#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
5.84k
{
155
5.84k
  struct json_tokener *tok;
156
157
5.84k
  if (depth < 1)
158
0
    return NULL;
159
160
5.84k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
5.84k
  if (!tok)
162
0
    return NULL;
163
5.84k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
5.84k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
5.84k
  tok->pb = printbuf_new();
170
5.84k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
5.84k
  tok->max_depth = depth;
177
5.84k
  json_tokener_reset(tok);
178
5.84k
  return tok;
179
5.84k
}
180
181
struct json_tokener *json_tokener_new(void)
182
5.84k
{
183
5.84k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
5.84k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
5.84k
{
188
5.84k
  if (!tok)
189
0
    return;
190
5.84k
  json_tokener_reset(tok);
191
5.84k
  if (tok->pb)
192
5.84k
    printbuf_free(tok->pb);
193
5.84k
  free(tok->stack);
194
5.84k
  free(tok);
195
5.84k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
271k
{
199
271k
  tok->stack[depth].state = json_tokener_state_eatws;
200
271k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
271k
  json_object_put(tok->stack[depth].current);
202
271k
  tok->stack[depth].current = NULL;
203
271k
  free(tok->stack[depth].obj_field_name);
204
271k
  tok->stack[depth].obj_field_name = NULL;
205
271k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
11.6k
{
209
11.6k
  int i;
210
11.6k
  if (!tok)
211
0
    return;
212
213
24.3k
  for (i = tok->depth; i >= 0; i--)
214
12.6k
    json_tokener_reset_level(tok, i);
215
11.6k
  tok->depth = 0;
216
11.6k
  tok->err = json_tokener_success;
217
11.6k
}
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
3.64M
#define state tok->stack[tok->depth].state
262
1.42M
#define saved_state tok->stack[tok->depth].saved_state
263
531k
#define current tok->stack[tok->depth].current
264
485k
#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.43M
  (((tok)->char_offset == len)                                         \
286
3.43M
       ? (((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.43M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.43M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.43M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.43M
              : (((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
5.87M
#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
291k
  do {                                                  \
308
291k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
291k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
291k
  } 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
5.84k
{
319
5.84k
  struct json_object *obj = NULL;
320
5.84k
  char c = '\1';
321
5.84k
  unsigned int nBytes = 0;
322
5.84k
  unsigned int *nBytesp = &nBytes;
323
324
5.84k
#ifdef HAVE_USELOCALE
325
5.84k
  locale_t oldlocale = uselocale(NULL);
326
5.84k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
5.84k
  tok->char_offset = 0;
332
5.84k
  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
5.84k
  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
5.84k
#ifdef HAVE_USELOCALE
347
5.84k
  {
348
5.84k
#ifdef HAVE_DUPLOCALE
349
5.84k
    locale_t duploc = duplocale(oldlocale);
350
5.84k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
5.84k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
5.84k
    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
5.84k
    uselocale(newloc);
375
5.84k
  }
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
746k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
746k
  {
395
396
1.87M
  redo_char:
397
1.87M
    switch (state)
398
1.87M
    {
399
400
729k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
961k
      while (is_ws_char(c))
403
231k
      {
404
231k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
231k
      }
407
729k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
1.06k
      {
409
1.06k
        printbuf_reset(tok->pb);
410
1.06k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
1.06k
        state = json_tokener_state_comment_start;
412
1.06k
      }
413
728k
      else
414
728k
      {
415
728k
        state = saved_state;
416
728k
        goto redo_char;
417
728k
      }
418
1.06k
      break;
419
420
132k
    case json_tokener_state_start:
421
132k
      switch (c)
422
132k
      {
423
42.8k
      case '{':
424
42.8k
        state = json_tokener_state_eatws;
425
42.8k
        saved_state = json_tokener_state_object_field_start;
426
42.8k
        current = json_object_new_object();
427
42.8k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
42.8k
        break;
433
42.8k
      case '[':
434
9.46k
        state = json_tokener_state_eatws;
435
9.46k
        saved_state = json_tokener_state_array;
436
9.46k
        current = json_object_new_array();
437
9.46k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
9.46k
        break;
443
9.46k
      case 'I':
444
15
      case 'i':
445
15
        state = json_tokener_state_inf;
446
15
        printbuf_reset(tok->pb);
447
15
        tok->st_pos = 0;
448
15
        goto redo_char;
449
131
      case 'N':
450
378
      case 'n':
451
378
        state = json_tokener_state_null; // or NaN
452
378
        printbuf_reset(tok->pb);
453
378
        tok->st_pos = 0;
454
378
        goto redo_char;
455
79
      case '\'':
456
79
        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
67.9k
      case '"':
464
67.9k
        state = json_tokener_state_string;
465
67.9k
        printbuf_reset(tok->pb);
466
67.9k
        tok->quote_char = c;
467
67.9k
        break;
468
22
      case 'T':
469
67
      case 't':
470
193
      case 'F':
471
319
      case 'f':
472
319
        state = json_tokener_state_boolean;
473
319
        printbuf_reset(tok->pb);
474
319
        tok->st_pos = 0;
475
319
        goto redo_char;
476
2.85k
      case '0':
477
5.45k
      case '1':
478
6.31k
      case '2':
479
6.69k
      case '3':
480
8.26k
      case '4':
481
8.92k
      case '5':
482
9.06k
      case '6':
483
9.19k
      case '7':
484
9.27k
      case '8':
485
9.69k
      case '9':
486
11.7k
      case '-':
487
11.7k
        state = json_tokener_state_number;
488
11.7k
        printbuf_reset(tok->pb);
489
11.7k
        tok->is_double = 0;
490
11.7k
        goto redo_char;
491
75
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
132k
      }
493
120k
      break;
494
495
131k
    case json_tokener_state_finish:
496
131k
      if (tok->depth == 0)
497
5.41k
        goto out;
498
125k
      obj = json_object_get(current);
499
125k
      json_tokener_reset_level(tok, tok->depth);
500
125k
      tok->depth--;
501
125k
      goto redo_char;
502
503
17
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
17
    {
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
17
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
44
      while (tok->st_pos < (int)json_inf_str_len)
516
44
      {
517
44
        char inf_char = *str;
518
44
        if (inf_char != json_inf_str[tok->st_pos] &&
519
34
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
34
              inf_char != json_inf_str_invert[tok->st_pos])
521
44
           )
522
17
        {
523
17
          tok->err = json_tokener_error_parse_unexpected;
524
17
          goto out;
525
17
        }
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.70k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.70k
    {
555
1.70k
      int size;
556
1.70k
      int size_nan;
557
1.70k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.70k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.70k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.70k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.70k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
397
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
1.31k
      {
564
1.31k
        if (tok->st_pos == json_null_str_len)
565
232
        {
566
232
          current = NULL;
567
232
          saved_state = json_tokener_state_finish;
568
232
          state = json_tokener_state_eatws;
569
232
          goto redo_char;
570
232
        }
571
1.31k
      }
572
397
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
397
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
22
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
375
      {
576
375
        if (tok->st_pos == json_nan_str_len)
577
124
        {
578
124
          current = json_object_new_double(NAN);
579
124
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
124
          saved_state = json_tokener_state_finish;
585
124
          state = json_tokener_state_eatws;
586
124
          goto redo_char;
587
124
        }
588
375
      }
589
22
      else
590
22
      {
591
22
        tok->err = json_tokener_error_parse_null;
592
22
        goto out;
593
22
      }
594
1.33k
      tok->st_pos++;
595
1.33k
    }
596
0
    break;
597
598
1.06k
    case json_tokener_state_comment_start:
599
1.06k
      if (c == '*')
600
280
      {
601
280
        state = json_tokener_state_comment;
602
280
      }
603
783
      else if (c == '/')
604
769
      {
605
769
        state = json_tokener_state_comment_eol;
606
769
      }
607
14
      else
608
14
      {
609
14
        tok->err = json_tokener_error_parse_comment;
610
14
        goto out;
611
14
      }
612
1.04k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
1.04k
      break;
614
615
1.43k
    case json_tokener_state_comment:
616
1.43k
    {
617
      /* Advance until we change state */
618
1.43k
      const char *case_start = str;
619
23.0k
      while (c != '*')
620
21.6k
      {
621
21.6k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
25
        {
623
25
          printbuf_memappend_checked(tok->pb, case_start,
624
25
                                     str - case_start);
625
25
          goto out;
626
25
        }
627
21.6k
      }
628
1.41k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.41k
      state = json_tokener_state_comment_end;
630
1.41k
    }
631
0
    break;
632
633
769
    case json_tokener_state_comment_eol:
634
769
    {
635
      /* Advance until we change state */
636
769
      const char *case_start = str;
637
57.5k
      while (c != '\n')
638
56.8k
      {
639
56.8k
        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
56.8k
      }
646
724
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
724
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
724
      state = json_tokener_state_eatws;
649
724
    }
650
0
    break;
651
652
1.41k
    case json_tokener_state_comment_end:
653
1.41k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.41k
      if (c == '/')
655
249
      {
656
249
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
249
        state = json_tokener_state_eatws;
658
249
      }
659
1.16k
      else
660
1.16k
      {
661
1.16k
        state = json_tokener_state_comment;
662
1.16k
      }
663
1.41k
      break;
664
665
113k
    case json_tokener_state_string:
666
113k
    {
667
      /* Advance until we change state */
668
113k
      const char *case_start = str;
669
1.65M
      while (1)
670
1.65M
      {
671
1.65M
        if (c == tok->quote_char)
672
67.8k
        {
673
67.8k
          printbuf_memappend_checked(tok->pb, case_start,
674
67.8k
                                     str - case_start);
675
67.8k
          current =
676
67.8k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
67.8k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
67.8k
          saved_state = json_tokener_state_finish;
683
67.8k
          state = json_tokener_state_eatws;
684
67.8k
          break;
685
67.8k
        }
686
1.59M
        else if (c == '\\')
687
45.4k
        {
688
45.4k
          printbuf_memappend_checked(tok->pb, case_start,
689
45.4k
                                     str - case_start);
690
45.4k
          saved_state = json_tokener_state_string;
691
45.4k
          state = json_tokener_state_string_escape;
692
45.4k
          break;
693
45.4k
        }
694
1.54M
        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.54M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
41
        {
702
41
          printbuf_memappend_checked(tok->pb, case_start,
703
41
                                     str - case_start);
704
41
          goto out;
705
41
        }
706
1.54M
      }
707
113k
    }
708
113k
    break;
709
710
113k
    case json_tokener_state_string_escape:
711
52.6k
      switch (c)
712
52.6k
      {
713
10.0k
      case '"':
714
31.0k
      case '\\':
715
31.2k
      case '/':
716
31.2k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
31.2k
        state = saved_state;
718
31.2k
        break;
719
685
      case 'b':
720
17.8k
      case 'n':
721
18.0k
      case 'r':
722
18.6k
      case 't':
723
19.0k
      case 'f':
724
19.0k
        if (c == 'b')
725
685
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
18.3k
        else if (c == 'n')
727
17.1k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.20k
        else if (c == 'r')
729
282
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
923
        else if (c == 't')
731
559
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
364
        else if (c == 'f')
733
364
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
19.0k
        state = saved_state;
735
19.0k
        break;
736
2.39k
      case 'u':
737
2.39k
        tok->ucs_char = 0;
738
2.39k
        tok->st_pos = 0;
739
2.39k
        state = json_tokener_state_escape_unicode;
740
2.39k
        break;
741
11
      default: tok->err = json_tokener_error_parse_string; goto out;
742
52.6k
      }
743
52.6k
      break;
744
745
      // ===================================================
746
747
52.6k
    case json_tokener_state_escape_unicode:
748
2.82k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
11.2k
      while (1)
751
11.2k
      {
752
11.2k
        if (!c || !is_hex_char(c))
753
14
        {
754
14
          tok->err = json_tokener_error_parse_string;
755
14
          goto out;
756
14
        }
757
11.2k
        tok->ucs_char |=
758
11.2k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
11.2k
        tok->st_pos++;
760
11.2k
        if (tok->st_pos >= 4)
761
2.81k
          break;
762
763
8.46k
        (void)ADVANCE_CHAR(str, tok);
764
8.46k
        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.46k
      }
775
2.81k
      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.81k
      if (tok->high_surrogate)
781
435
      {
782
435
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
295
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
295
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
295
                                                tok->ucs_char);
787
295
        }
788
140
        else
789
140
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
140
          printbuf_memappend_checked(tok->pb,
794
140
                                     (char *)utf8_replacement_char, 3);
795
140
        }
796
435
        tok->high_surrogate = 0;
797
435
      }
798
799
2.81k
      if (tok->ucs_char < 0x80)
800
1.00k
      {
801
1.00k
        unsigned char unescaped_utf[1];
802
1.00k
        unescaped_utf[0] = tok->ucs_char;
803
1.00k
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
1.00k
      }
805
1.81k
      else if (tok->ucs_char < 0x800)
806
40
      {
807
40
        unsigned char unescaped_utf[2];
808
40
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
40
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
40
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
40
      }
812
1.77k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
700
      {
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
700
        tok->high_surrogate = tok->ucs_char;
829
700
        tok->ucs_char = 0;
830
700
        state = json_tokener_state_escape_unicode_need_escape;
831
700
        break;
832
700
      }
833
1.07k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
351
      {
835
        /* Got a low surrogate not preceded by a high */
836
351
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
351
      }
838
719
      else if (tok->ucs_char < 0x10000)
839
424
      {
840
424
        unsigned char unescaped_utf[3];
841
424
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
424
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
424
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
424
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
424
      }
846
295
      else if (tok->ucs_char < 0x110000)
847
295
      {
848
295
        unsigned char unescaped_utf[4];
849
295
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
295
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
295
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
295
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
295
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
295
      }
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.11k
      state = saved_state; // i.e. _state_string or _state_object_field
861
2.11k
    }
862
0
    break;
863
864
700
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
700
      if (!c || c != '\\')
868
159
      {
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
159
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
159
        tok->high_surrogate = 0;
875
159
        tok->ucs_char = 0;
876
159
        tok->st_pos = 0;
877
159
        state = saved_state;
878
159
        goto redo_char;
879
159
      }
880
541
      state = json_tokener_state_escape_unicode_need_u;
881
541
      break;
882
883
541
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
541
      if (!c || c != 'u')
886
104
      {
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
104
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
104
        tok->high_surrogate = 0;
894
104
        tok->ucs_char = 0;
895
104
        tok->st_pos = 0;
896
104
        state = json_tokener_state_string_escape;
897
104
        goto redo_char;
898
104
      }
899
437
      state = json_tokener_state_escape_unicode;
900
437
      break;
901
902
      // ===================================================
903
904
1.77k
    case json_tokener_state_boolean:
905
1.77k
    {
906
1.77k
      int size1, size2;
907
1.77k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.77k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.77k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.77k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.77k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.49k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
283
      {
914
283
        if (tok->st_pos == json_true_str_len)
915
53
        {
916
53
          current = json_object_new_boolean(1);
917
53
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
53
          saved_state = json_tokener_state_finish;
923
53
          state = json_tokener_state_eatws;
924
53
          goto redo_char;
925
53
        }
926
283
      }
927
1.49k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.49k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
24
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.47k
      {
931
1.47k
        if (tok->st_pos == json_false_str_len)
932
242
        {
933
242
          current = json_object_new_boolean(0);
934
242
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
242
          saved_state = json_tokener_state_finish;
940
242
          state = json_tokener_state_eatws;
941
242
          goto redo_char;
942
242
        }
943
1.47k
      }
944
24
      else
945
24
      {
946
24
        tok->err = json_tokener_error_parse_boolean;
947
24
        goto out;
948
24
      }
949
1.46k
      tok->st_pos++;
950
1.46k
    }
951
0
    break;
952
953
11.7k
    case json_tokener_state_number:
954
11.7k
    {
955
      /* Advance until we change state */
956
11.7k
      const char *case_start = str;
957
11.7k
      int case_len = 0;
958
11.7k
      int is_exponent = 0;
959
11.7k
      int neg_sign_ok = 1;
960
11.7k
      int pos_sign_ok = 0;
961
11.7k
      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
84.5k
      while (c && ((c >= '0' && c <= '9') ||
986
15.1k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
14.6k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
12.2k
                   (!tok->is_double && c == '.')))
989
72.8k
      {
990
72.8k
        pos_sign_ok = neg_sign_ok = 0;
991
72.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
72.8k
        switch (c)
1000
72.8k
        {
1001
495
        case '.':
1002
495
          tok->is_double = 1;
1003
495
          pos_sign_ok = 1;
1004
495
          neg_sign_ok = 1;
1005
495
          break;
1006
455
        case 'e': /* FALLTHRU */
1007
486
        case 'E':
1008
486
          is_exponent = 1;
1009
486
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
486
          pos_sign_ok = neg_sign_ok = 1;
1012
486
          break;
1013
71.8k
        default: break;
1014
72.8k
        }
1015
1016
72.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
72.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
11.7k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
937
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
35
      {
1033
35
        tok->err = json_tokener_error_parse_number;
1034
35
        goto out;
1035
35
      }
1036
11.7k
      if (case_len > 0)
1037
11.7k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
11.7k
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1041
2
      {
1042
2
        state = json_tokener_state_inf;
1043
2
        tok->st_pos = 0;
1044
2
        goto redo_char;
1045
2
      }
1046
11.7k
      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
11.7k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1115
568
      {
1116
        /* Trim some chars off the end, to allow things
1117
           like "123e+" to parse ok. */
1118
1.17k
        while (printbuf_length(tok->pb) > 1)
1119
1.14k
        {
1120
1.14k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1121
1.14k
          if (last_char != 'e' && last_char != 'E' &&
1122
822
              last_char != '-' && last_char != '+')
1123
545
          {
1124
545
            break;
1125
545
          }
1126
602
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1127
602
          printbuf_length(tok->pb)--;
1128
602
        }
1129
568
      }
1130
11.7k
    }
1131
0
      {
1132
11.7k
        int64_t num64;
1133
11.7k
        uint64_t numuint64;
1134
11.7k
        double numd;
1135
11.7k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1136
1.57k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1137
1.56k
        {
1138
1.56k
          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.56k
          current = json_object_new_int64(num64);
1144
1.56k
          if (current == NULL)
1145
0
          {
1146
0
            tok->err = json_tokener_error_memory;
1147
0
            goto out;
1148
0
          }
1149
1.56k
        }
1150
10.1k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1151
9.56k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1152
9.56k
        {
1153
9.56k
          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.56k
          if (numuint64 <= INT64_MAX)
1159
9.07k
          {
1160
9.07k
            num64 = (uint64_t)numuint64;
1161
9.07k
            current = json_object_new_int64(num64);
1162
9.07k
            if (current == NULL)
1163
0
            {
1164
0
              tok->err = json_tokener_error_memory;
1165
0
              goto out;
1166
0
            }
1167
9.07k
          }
1168
487
          else
1169
487
          {
1170
487
            current = json_object_new_uint64(numuint64);
1171
487
            if (current == NULL)
1172
0
            {
1173
0
              tok->err = json_tokener_error_memory;
1174
0
              goto out;
1175
0
            }
1176
487
          }
1177
9.56k
        }
1178
571
        else if (tok->is_double &&
1179
568
                 json_tokener_parse_double(
1180
568
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1181
566
        {
1182
566
          current = json_object_new_double_s(numd, tok->pb->buf);
1183
566
          if (current == NULL)
1184
0
          {
1185
0
            tok->err = json_tokener_error_memory;
1186
0
            goto out;
1187
0
          }
1188
566
        }
1189
5
        else
1190
5
        {
1191
5
          tok->err = json_tokener_error_parse_number;
1192
5
          goto out;
1193
5
        }
1194
11.6k
        saved_state = json_tokener_state_finish;
1195
11.6k
        state = json_tokener_state_eatws;
1196
11.6k
        goto redo_char;
1197
11.7k
      }
1198
0
      break;
1199
1200
20.5k
    case json_tokener_state_array_after_sep:
1201
29.9k
    case json_tokener_state_array:
1202
29.9k
      if (c == ']')
1203
419
      {
1204
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1205
419
        json_object_array_shrink(current, 0);
1206
1207
419
        if (state == json_tokener_state_array_after_sep &&
1208
23
            (tok->flags & JSON_TOKENER_STRICT))
1209
0
        {
1210
0
          tok->err = json_tokener_error_parse_unexpected;
1211
0
          goto out;
1212
0
        }
1213
419
        saved_state = json_tokener_state_finish;
1214
419
        state = json_tokener_state_eatws;
1215
419
      }
1216
29.5k
      else
1217
29.5k
      {
1218
29.5k
        if (tok->depth >= tok->max_depth - 1)
1219
1
        {
1220
1
          tok->err = json_tokener_error_depth;
1221
1
          goto out;
1222
1
        }
1223
29.5k
        state = json_tokener_state_array_add;
1224
29.5k
        tok->depth++;
1225
29.5k
        json_tokener_reset_level(tok, tok->depth);
1226
29.5k
        goto redo_char;
1227
29.5k
      }
1228
419
      break;
1229
1230
29.1k
    case json_tokener_state_array_add:
1231
29.1k
      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
29.1k
      saved_state = json_tokener_state_array_sep;
1237
29.1k
      state = json_tokener_state_eatws;
1238
29.1k
      goto redo_char;
1239
1240
29.1k
    case json_tokener_state_array_sep:
1241
29.1k
      if (c == ']')
1242
8.57k
      {
1243
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1244
8.57k
        json_object_array_shrink(current, 0);
1245
1246
8.57k
        saved_state = json_tokener_state_finish;
1247
8.57k
        state = json_tokener_state_eatws;
1248
8.57k
      }
1249
20.5k
      else if (c == ',')
1250
20.5k
      {
1251
20.5k
        saved_state = json_tokener_state_array_after_sep;
1252
20.5k
        state = json_tokener_state_eatws;
1253
20.5k
      }
1254
18
      else
1255
18
      {
1256
18
        tok->err = json_tokener_error_parse_array;
1257
18
        goto out;
1258
18
      }
1259
29.0k
      break;
1260
1261
42.8k
    case json_tokener_state_object_field_start:
1262
113k
    case json_tokener_state_object_field_start_after_sep:
1263
113k
      if (c == '}')
1264
16.2k
      {
1265
16.2k
        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
16.2k
        saved_state = json_tokener_state_finish;
1272
16.2k
        state = json_tokener_state_eatws;
1273
16.2k
      }
1274
97.4k
      else if (c == '"' || c == '\'')
1275
97.4k
      {
1276
97.4k
        tok->quote_char = c;
1277
97.4k
        printbuf_reset(tok->pb);
1278
97.4k
        state = json_tokener_state_object_field;
1279
97.4k
      }
1280
19
      else
1281
19
      {
1282
19
        tok->err = json_tokener_error_parse_object_key_name;
1283
19
        goto out;
1284
19
      }
1285
113k
      break;
1286
1287
113k
    case json_tokener_state_object_field:
1288
104k
    {
1289
      /* Advance until we change state */
1290
104k
      const char *case_start = str;
1291
855k
      while (1)
1292
855k
      {
1293
855k
        if (c == tok->quote_char)
1294
97.4k
        {
1295
97.4k
          printbuf_memappend_checked(tok->pb, case_start,
1296
97.4k
                                     str - case_start);
1297
97.4k
          obj_field_name = strdup(tok->pb->buf);
1298
97.4k
          if (obj_field_name == NULL)
1299
0
          {
1300
0
            tok->err = json_tokener_error_memory;
1301
0
            goto out;
1302
0
          }
1303
97.4k
          saved_state = json_tokener_state_object_field_end;
1304
97.4k
          state = json_tokener_state_eatws;
1305
97.4k
          break;
1306
97.4k
        }
1307
757k
        else if (c == '\\')
1308
7.08k
        {
1309
7.08k
          printbuf_memappend_checked(tok->pb, case_start,
1310
7.08k
                                     str - case_start);
1311
7.08k
          saved_state = json_tokener_state_object_field;
1312
7.08k
          state = json_tokener_state_string_escape;
1313
7.08k
          break;
1314
7.08k
        }
1315
750k
        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
750k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1322
18
        {
1323
18
          printbuf_memappend_checked(tok->pb, case_start,
1324
18
                                     str - case_start);
1325
18
          goto out;
1326
18
        }
1327
750k
      }
1328
104k
    }
1329
104k
    break;
1330
1331
104k
    case json_tokener_state_object_field_end:
1332
97.4k
      if (c == ':')
1333
97.3k
      {
1334
97.3k
        saved_state = json_tokener_state_object_value;
1335
97.3k
        state = json_tokener_state_eatws;
1336
97.3k
      }
1337
19
      else
1338
19
      {
1339
19
        tok->err = json_tokener_error_parse_object_key_sep;
1340
19
        goto out;
1341
19
      }
1342
97.3k
      break;
1343
1344
97.3k
    case json_tokener_state_object_value:
1345
97.3k
      if (tok->depth >= tok->max_depth - 1)
1346
0
      {
1347
0
        tok->err = json_tokener_error_depth;
1348
0
        goto out;
1349
0
      }
1350
97.3k
      state = json_tokener_state_object_value_add;
1351
97.3k
      tok->depth++;
1352
97.3k
      json_tokener_reset_level(tok, tok->depth);
1353
97.3k
      goto redo_char;
1354
1355
96.8k
    case json_tokener_state_object_value_add:
1356
96.8k
      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
96.8k
      free(obj_field_name);
1362
96.8k
      obj_field_name = NULL;
1363
96.8k
      saved_state = json_tokener_state_object_sep;
1364
96.8k
      state = json_tokener_state_eatws;
1365
96.8k
      goto redo_char;
1366
1367
96.8k
    case json_tokener_state_object_sep:
1368
      /* { */
1369
96.8k
      if (c == '}')
1370
25.9k
      {
1371
25.9k
        saved_state = json_tokener_state_finish;
1372
25.9k
        state = json_tokener_state_eatws;
1373
25.9k
      }
1374
70.9k
      else if (c == ',')
1375
70.8k
      {
1376
70.8k
        saved_state = json_tokener_state_object_field_start_after_sep;
1377
70.8k
        state = json_tokener_state_eatws;
1378
70.8k
      }
1379
15
      else
1380
15
      {
1381
15
        tok->err = json_tokener_error_parse_object_value_sep;
1382
15
        goto out;
1383
15
      }
1384
96.8k
      break;
1385
1.87M
    }
1386
740k
    (void)ADVANCE_CHAR(str, tok);
1387
740k
    if (!c) // This is the char *before* advancing
1388
6
      break;
1389
740k
  } /* while(PEEK_CHAR) */
1390
1391
5.84k
out:
1392
5.84k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1393
0
  {
1394
0
    tok->err = json_tokener_error_parse_utf8_string;
1395
0
  }
1396
5.84k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1397
55
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1398
55
          JSON_TOKENER_STRICT)
1399
0
  {
1400
    /* unexpected char after JSON data */
1401
0
    tok->err = json_tokener_error_parse_unexpected;
1402
0
  }
1403
5.84k
  if (!c)
1404
5.57k
  {
1405
    /* We hit an eof char (0) */
1406
5.57k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1407
176
      tok->err = json_tokener_error_parse_eof;
1408
5.57k
  }
1409
1410
5.84k
#ifdef HAVE_USELOCALE
1411
5.84k
  uselocale(oldlocale);
1412
5.84k
  freelocale(newloc);
1413
#elif defined(HAVE_SETLOCALE)
1414
  setlocale(LC_NUMERIC, oldlocale);
1415
  free(oldlocale);
1416
#endif
1417
1418
5.84k
  if (tok->err == json_tokener_success)
1419
5.45k
  {
1420
5.45k
    json_object *ret = json_object_get(current);
1421
5.45k
    int ii;
1422
1423
    /* Partially reset, so we parse additional objects on subsequent calls. */
1424
10.9k
    for (ii = tok->depth; ii >= 0; ii--)
1425
5.53k
      json_tokener_reset_level(tok, ii);
1426
5.45k
    return ret;
1427
5.45k
  }
1428
1429
383
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1430
383
           tok->char_offset);
1431
383
  return NULL;
1432
5.84k
}
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
568
{
1473
568
  char *end;
1474
568
  *retval = strtod(buf, &end);
1475
568
  if (buf + len == end)
1476
566
    return 0; // It worked
1477
2
  return 1;
1478
568
}