Coverage Report

Created: 2026-07-16 06:59

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.6k
#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.03M
{
71
1.03M
  return c == ' '
72
835k
      || c == '\t'
73
810k
      || c == '\n'
74
807k
      || c == '\r';
75
1.03M
}
76
77
static inline int is_hex_char(char c)
78
11.6k
{
79
11.6k
  return (c >= '0' && c <= '9')
80
3.80k
      || (c >= 'A' && c <= 'F')
81
283
      || (c >= 'a' && c <= 'f');
82
11.6k
}
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
397
{
134
397
  int jerr_int = (int)jerr;
135
397
  if (jerr_int < 0 ||
136
397
      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
397
  return json_tokener_errors[jerr];
140
397
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
794
{
144
794
  return tok->err;
145
794
}
146
147
/* Stuff for decoding unicode sequences */
148
1.93k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.65k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
284
#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
6.76k
{
155
6.76k
  struct json_tokener *tok;
156
157
6.76k
  if (depth < 1)
158
0
    return NULL;
159
160
6.76k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
6.76k
  if (!tok)
162
0
    return NULL;
163
6.76k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
6.76k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
6.76k
  tok->pb = printbuf_new();
170
6.76k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
6.76k
  tok->max_depth = depth;
177
6.76k
  json_tokener_reset(tok);
178
6.76k
  return tok;
179
6.76k
}
180
181
struct json_tokener *json_tokener_new(void)
182
6.76k
{
183
6.76k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
6.76k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
6.76k
{
188
6.76k
  if (!tok)
189
0
    return;
190
6.76k
  json_tokener_reset(tok);
191
6.76k
  if (tok->pb)
192
6.76k
    printbuf_free(tok->pb);
193
6.76k
  free(tok->stack);
194
6.76k
  free(tok);
195
6.76k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
299k
{
199
299k
  tok->stack[depth].state = json_tokener_state_eatws;
200
299k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
299k
  json_object_put(tok->stack[depth].current);
202
299k
  tok->stack[depth].current = NULL;
203
299k
  free(tok->stack[depth].obj_field_name);
204
299k
  tok->stack[depth].obj_field_name = NULL;
205
299k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
13.5k
{
209
13.5k
  int i;
210
13.5k
  if (!tok)
211
0
    return;
212
213
28.0k
  for (i = tok->depth; i >= 0; i--)
214
14.5k
    json_tokener_reset_level(tok, i);
215
13.5k
  tok->depth = 0;
216
13.5k
  tok->err = json_tokener_success;
217
13.5k
}
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.01M
#define state tok->stack[tok->depth].state
262
1.57M
#define saved_state tok->stack[tok->depth].saved_state
263
585k
#define current tok->stack[tok->depth].current
264
541k
#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.64M
  (((tok)->char_offset == len)                                         \
286
3.64M
       ? (((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.64M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.64M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.64M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.64M
              : (((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.22M
#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
310k
  do {                                                  \
308
310k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
310k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
310k
  } 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
6.76k
{
319
6.76k
  struct json_object *obj = NULL;
320
6.76k
  char c = '\1';
321
6.76k
  unsigned int nBytes = 0;
322
6.76k
  unsigned int *nBytesp = &nBytes;
323
324
6.76k
#ifdef HAVE_USELOCALE
325
6.76k
  locale_t oldlocale = uselocale(NULL);
326
6.76k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
6.76k
  tok->char_offset = 0;
332
6.76k
  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
6.76k
  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
6.76k
#ifdef HAVE_USELOCALE
347
6.76k
  {
348
6.76k
#ifdef HAVE_DUPLOCALE
349
6.76k
    locale_t duploc = duplocale(oldlocale);
350
6.76k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
6.76k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
6.76k
    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
6.76k
    uselocale(newloc);
375
6.76k
  }
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
818k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
818k
  {
395
396
2.06M
  redo_char:
397
2.06M
    switch (state)
398
2.06M
    {
399
400
807k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
1.03M
      while (is_ws_char(c))
403
228k
      {
404
228k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
228k
      }
407
807k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
1.09k
      {
409
1.09k
        printbuf_reset(tok->pb);
410
1.09k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
1.09k
        state = json_tokener_state_comment_start;
412
1.09k
      }
413
806k
      else
414
806k
      {
415
806k
        state = saved_state;
416
806k
        goto redo_char;
417
806k
      }
418
1.09k
      break;
419
420
146k
    case json_tokener_state_start:
421
146k
      switch (c)
422
146k
      {
423
49.2k
      case '{':
424
49.2k
        state = json_tokener_state_eatws;
425
49.2k
        saved_state = json_tokener_state_object_field_start;
426
49.2k
        current = json_object_new_object();
427
49.2k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
49.2k
        break;
433
49.2k
      case '[':
434
10.2k
        state = json_tokener_state_eatws;
435
10.2k
        saved_state = json_tokener_state_array;
436
10.2k
        current = json_object_new_array();
437
10.2k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
10.2k
        break;
443
10.2k
      case 'I':
444
12
      case 'i':
445
12
        state = json_tokener_state_inf;
446
12
        printbuf_reset(tok->pb);
447
12
        tok->st_pos = 0;
448
12
        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
87
      case '\'':
456
87
        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
74.5k
      case '"':
464
74.5k
        state = json_tokener_state_string;
465
74.5k
        printbuf_reset(tok->pb);
466
74.5k
        tok->quote_char = c;
467
74.5k
        break;
468
23
      case 'T':
469
67
      case 't':
470
192
      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.66k
      case '0':
477
5.32k
      case '1':
478
6.22k
      case '2':
479
6.61k
      case '3':
480
8.03k
      case '4':
481
8.65k
      case '5':
482
8.79k
      case '6':
483
8.92k
      case '7':
484
8.99k
      case '8':
485
9.42k
      case '9':
486
11.4k
      case '-':
487
11.4k
        state = json_tokener_state_number;
488
11.4k
        printbuf_reset(tok->pb);
489
11.4k
        tok->is_double = 0;
490
11.4k
        goto redo_char;
491
81
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
146k
      }
493
134k
      break;
494
495
145k
    case json_tokener_state_finish:
496
145k
      if (tok->depth == 0)
497
6.33k
        goto out;
498
138k
      obj = json_object_get(current);
499
138k
      json_tokener_reset_level(tok, tok->depth);
500
138k
      tok->depth--;
501
138k
      goto redo_char;
502
503
13
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
13
    {
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
13
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
33
      while (tok->st_pos < (int)json_inf_str_len)
516
33
      {
517
33
        char inf_char = *str;
518
33
        if (inf_char != json_inf_str[tok->st_pos] &&
519
26
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
26
              inf_char != json_inf_str_invert[tok->st_pos])
521
33
           )
522
13
        {
523
13
          tok->err = json_tokener_error_parse_unexpected;
524
13
          goto out;
525
13
        }
526
20
        tok->st_pos++;
527
20
        (void)ADVANCE_CHAR(str, tok);
528
20
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
20
      }
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
400
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
1.30k
      {
564
1.30k
        if (tok->st_pos == json_null_str_len)
565
229
        {
566
229
          current = NULL;
567
229
          saved_state = json_tokener_state_finish;
568
229
          state = json_tokener_state_eatws;
569
229
          goto redo_char;
570
229
        }
571
1.30k
      }
572
400
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
400
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
25
               (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
25
      else
590
25
      {
591
25
        tok->err = json_tokener_error_parse_null;
592
25
        goto out;
593
25
      }
594
1.32k
      tok->st_pos++;
595
1.32k
    }
596
0
    break;
597
598
1.09k
    case json_tokener_state_comment_start:
599
1.09k
      if (c == '*')
600
280
      {
601
280
        state = json_tokener_state_comment;
602
280
      }
603
819
      else if (c == '/')
604
806
      {
605
806
        state = json_tokener_state_comment_eol;
606
806
      }
607
13
      else
608
13
      {
609
13
        tok->err = json_tokener_error_parse_comment;
610
13
        goto out;
611
13
      }
612
1.08k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
1.08k
      break;
614
615
1.39k
    case json_tokener_state_comment:
616
1.39k
    {
617
      /* Advance until we change state */
618
1.39k
      const char *case_start = str;
619
22.0k
      while (c != '*')
620
20.6k
      {
621
20.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
20.6k
      }
628
1.37k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.37k
      state = json_tokener_state_comment_end;
630
1.37k
    }
631
0
    break;
632
633
806
    case json_tokener_state_comment_eol:
634
806
    {
635
      /* Advance until we change state */
636
806
      const char *case_start = str;
637
57.1k
      while (c != '\n')
638
56.3k
      {
639
56.3k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
41
        {
641
41
          printbuf_memappend_checked(tok->pb, case_start,
642
41
                                     str - case_start);
643
41
          goto out;
644
41
        }
645
56.3k
      }
646
765
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
765
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
765
      state = json_tokener_state_eatws;
649
765
    }
650
0
    break;
651
652
1.37k
    case json_tokener_state_comment_end:
653
1.37k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.37k
      if (c == '/')
655
250
      {
656
250
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
250
        state = json_tokener_state_eatws;
658
250
      }
659
1.12k
      else
660
1.12k
      {
661
1.12k
        state = json_tokener_state_comment;
662
1.12k
      }
663
1.37k
      break;
664
665
120k
    case json_tokener_state_string:
666
120k
    {
667
      /* Advance until we change state */
668
120k
      const char *case_start = str;
669
1.73M
      while (1)
670
1.73M
      {
671
1.73M
        if (c == tok->quote_char)
672
74.5k
        {
673
74.5k
          printbuf_memappend_checked(tok->pb, case_start,
674
74.5k
                                     str - case_start);
675
74.5k
          current =
676
74.5k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
74.5k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
74.5k
          saved_state = json_tokener_state_finish;
683
74.5k
          state = json_tokener_state_eatws;
684
74.5k
          break;
685
74.5k
        }
686
1.65M
        else if (c == '\\')
687
45.6k
        {
688
45.6k
          printbuf_memappend_checked(tok->pb, case_start,
689
45.6k
                                     str - case_start);
690
45.6k
          saved_state = json_tokener_state_string;
691
45.6k
          state = json_tokener_state_string_escape;
692
45.6k
          break;
693
45.6k
        }
694
1.61M
        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.61M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
40
        {
702
40
          printbuf_memappend_checked(tok->pb, case_start,
703
40
                                     str - case_start);
704
40
          goto out;
705
40
        }
706
1.61M
      }
707
120k
    }
708
120k
    break;
709
710
120k
    case json_tokener_state_string_escape:
711
53.2k
      switch (c)
712
53.2k
      {
713
10.1k
      case '"':
714
31.4k
      case '\\':
715
31.6k
      case '/':
716
31.6k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
31.6k
        state = saved_state;
718
31.6k
        break;
719
760
      case 'b':
720
18.0k
      case 'n':
721
18.3k
      case 'r':
722
18.8k
      case 't':
723
19.1k
      case 'f':
724
19.1k
        if (c == 'b')
725
760
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
18.3k
        else if (c == 'n')
727
17.2k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.10k
        else if (c == 'r')
729
286
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
820
        else if (c == 't')
731
583
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
237
        else if (c == 'f')
733
237
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
19.1k
        state = saved_state;
735
19.1k
        break;
736
2.46k
      case 'u':
737
2.46k
        tok->ucs_char = 0;
738
2.46k
        tok->st_pos = 0;
739
2.46k
        state = json_tokener_state_escape_unicode;
740
2.46k
        break;
741
13
      default: tok->err = json_tokener_error_parse_string; goto out;
742
53.2k
      }
743
53.2k
      break;
744
745
      // ===================================================
746
747
53.2k
    case json_tokener_state_escape_unicode:
748
2.92k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
11.6k
      while (1)
751
11.6k
      {
752
11.6k
        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.6k
        tok->ucs_char |=
758
11.6k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
11.6k
        tok->st_pos++;
760
11.6k
        if (tok->st_pos >= 4)
761
2.90k
          break;
762
763
8.74k
        (void)ADVANCE_CHAR(str, tok);
764
8.74k
        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.74k
      }
775
2.90k
      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.90k
      if (tok->high_surrogate)
781
456
      {
782
456
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
284
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
284
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
284
                                                tok->ucs_char);
787
284
        }
788
172
        else
789
172
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
172
          printbuf_memappend_checked(tok->pb,
794
172
                                     (char *)utf8_replacement_char, 3);
795
172
        }
796
456
        tok->high_surrogate = 0;
797
456
      }
798
799
2.90k
      if (tok->ucs_char < 0x80)
800
926
      {
801
926
        unsigned char unescaped_utf[1];
802
926
        unescaped_utf[0] = tok->ucs_char;
803
926
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
926
      }
805
1.98k
      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.93k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
743
      {
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
743
        tok->high_surrogate = tok->ucs_char;
829
743
        tok->ucs_char = 0;
830
743
        state = json_tokener_state_escape_unicode_need_escape;
831
743
        break;
832
743
      }
833
1.19k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
416
      {
835
        /* Got a low surrogate not preceded by a high */
836
416
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
416
      }
838
780
      else if (tok->ucs_char < 0x10000)
839
496
      {
840
496
        unsigned char unescaped_utf[3];
841
496
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
496
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
496
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
496
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
496
      }
846
284
      else if (tok->ucs_char < 0x110000)
847
284
      {
848
284
        unsigned char unescaped_utf[4];
849
284
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
284
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
284
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
284
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
284
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
284
      }
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.16k
      state = saved_state; // i.e. _state_string or _state_object_field
861
2.16k
    }
862
0
    break;
863
864
743
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
743
      if (!c || c != '\\')
868
150
      {
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
150
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
150
        tok->high_surrogate = 0;
875
150
        tok->ucs_char = 0;
876
150
        tok->st_pos = 0;
877
150
        state = saved_state;
878
150
        goto redo_char;
879
150
      }
880
593
      state = json_tokener_state_escape_unicode_need_u;
881
593
      break;
882
883
593
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
593
      if (!c || c != 'u')
886
136
      {
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
136
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
136
        tok->high_surrogate = 0;
894
136
        tok->ucs_char = 0;
895
136
        tok->st_pos = 0;
896
136
        state = json_tokener_state_string_escape;
897
136
        goto redo_char;
898
136
      }
899
457
      state = json_tokener_state_escape_unicode;
900
457
      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
279
      {
914
279
        if (tok->st_pos == json_true_str_len)
915
52
        {
916
52
          current = json_object_new_boolean(1);
917
52
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
52
          saved_state = json_tokener_state_finish;
923
52
          state = json_tokener_state_eatws;
924
52
          goto redo_char;
925
52
        }
926
279
      }
927
1.49k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.49k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
26
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.46k
      {
931
1.46k
        if (tok->st_pos == json_false_str_len)
932
241
        {
933
241
          current = json_object_new_boolean(0);
934
241
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
241
          saved_state = json_tokener_state_finish;
940
241
          state = json_tokener_state_eatws;
941
241
          goto redo_char;
942
241
        }
943
1.46k
      }
944
26
      else
945
26
      {
946
26
        tok->err = json_tokener_error_parse_boolean;
947
26
        goto out;
948
26
      }
949
1.45k
      tok->st_pos++;
950
1.45k
    }
951
0
    break;
952
953
11.4k
    case json_tokener_state_number:
954
11.4k
    {
955
      /* Advance until we change state */
956
11.4k
      const char *case_start = str;
957
11.4k
      int case_len = 0;
958
11.4k
      int is_exponent = 0;
959
11.4k
      int neg_sign_ok = 1;
960
11.4k
      int pos_sign_ok = 0;
961
11.4k
      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
82.1k
      while (c && ((c >= '0' && c <= '9') ||
986
14.9k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
14.4k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
11.9k
                   (!tok->is_double && c == '.')))
989
70.6k
      {
990
70.6k
        pos_sign_ok = neg_sign_ok = 0;
991
70.6k
        ++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
70.6k
        switch (c)
1000
70.6k
        {
1001
526
        case '.':
1002
526
          tok->is_double = 1;
1003
526
          pos_sign_ok = 1;
1004
526
          neg_sign_ok = 1;
1005
526
          break;
1006
494
        case 'e': /* FALLTHRU */
1007
529
        case 'E':
1008
529
          is_exponent = 1;
1009
529
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
529
          pos_sign_ok = neg_sign_ok = 1;
1012
529
          break;
1013
69.6k
        default: break;
1014
70.6k
        }
1015
1016
70.6k
        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
70.6k
      }
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.4k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
1.02k
          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.4k
      if (case_len > 0)
1037
11.4k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
11.4k
      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
11.4k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
607
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
1.33k
        while (printbuf_length(tok->pb) > 1)
1051
1.31k
        {
1052
1.31k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
1.31k
          if (last_char != 'e' && last_char != 'E' &&
1054
921
              last_char != '-' && last_char != '+')
1055
580
          {
1056
580
            break;
1057
580
          }
1058
730
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
730
          printbuf_length(tok->pb)--;
1060
730
        }
1061
607
      }
1062
11.4k
    }
1063
0
      {
1064
11.4k
        int64_t num64;
1065
11.4k
        uint64_t numuint64;
1066
11.4k
        double numd;
1067
11.4k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
1.52k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
1.52k
        {
1070
1.52k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1071
0
          {
1072
0
            tok->err = json_tokener_error_parse_number;
1073
0
            goto out;
1074
0
          }
1075
1.52k
          current = json_object_new_int64(num64);
1076
1.52k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
1.52k
        }
1082
9.89k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
9.28k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
9.28k
        {
1085
9.28k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1086
0
          {
1087
0
            tok->err = json_tokener_error_parse_number;
1088
0
            goto out;
1089
0
          }
1090
9.28k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
1.85k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
9.28k
          if (numuint64 <= INT64_MAX)
1097
8.80k
          {
1098
8.80k
            num64 = (uint64_t)numuint64;
1099
8.80k
            current = json_object_new_int64(num64);
1100
8.80k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
8.80k
          }
1106
487
          else
1107
487
          {
1108
487
            current = json_object_new_uint64(numuint64);
1109
487
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
487
          }
1115
9.28k
        }
1116
610
        else if (tok->is_double &&
1117
607
                 json_tokener_parse_double(
1118
607
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
606
        {
1120
606
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
606
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
606
        }
1127
4
        else
1128
4
        {
1129
4
          tok->err = json_tokener_error_parse_number;
1130
4
          goto out;
1131
4
        }
1132
11.4k
        saved_state = json_tokener_state_finish;
1133
11.4k
        state = json_tokener_state_eatws;
1134
11.4k
        goto redo_char;
1135
11.4k
      }
1136
0
      break;
1137
1138
21.0k
    case json_tokener_state_array_after_sep:
1139
31.3k
    case json_tokener_state_array:
1140
31.3k
      if (c == ']')
1141
367
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
367
        json_object_array_shrink(current, 0);
1144
1145
367
        if (state == json_tokener_state_array_after_sep &&
1146
21
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
367
        saved_state = json_tokener_state_finish;
1152
367
        state = json_tokener_state_eatws;
1153
367
      }
1154
30.9k
      else
1155
30.9k
      {
1156
30.9k
        if (tok->depth >= tok->max_depth - 1)
1157
1
        {
1158
1
          tok->err = json_tokener_error_depth;
1159
1
          goto out;
1160
1
        }
1161
30.9k
        state = json_tokener_state_array_add;
1162
30.9k
        tok->depth++;
1163
30.9k
        json_tokener_reset_level(tok, tok->depth);
1164
30.9k
        goto redo_char;
1165
30.9k
      }
1166
367
      break;
1167
1168
30.5k
    case json_tokener_state_array_add:
1169
30.5k
      if (json_object_array_add(current, obj) != 0)
1170
0
      {
1171
0
        tok->err = json_tokener_error_memory;
1172
0
        goto out;
1173
0
      }
1174
30.5k
      saved_state = json_tokener_state_array_sep;
1175
30.5k
      state = json_tokener_state_eatws;
1176
30.5k
      goto redo_char;
1177
1178
30.5k
    case json_tokener_state_array_sep:
1179
30.5k
      if (c == ']')
1180
9.46k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
9.46k
        json_object_array_shrink(current, 0);
1183
1184
9.46k
        saved_state = json_tokener_state_finish;
1185
9.46k
        state = json_tokener_state_eatws;
1186
9.46k
      }
1187
21.0k
      else if (c == ',')
1188
21.0k
      {
1189
21.0k
        saved_state = json_tokener_state_array_after_sep;
1190
21.0k
        state = json_tokener_state_eatws;
1191
21.0k
      }
1192
22
      else
1193
22
      {
1194
22
        tok->err = json_tokener_error_parse_array;
1195
22
        goto out;
1196
22
      }
1197
30.5k
      break;
1198
1199
49.2k
    case json_tokener_state_object_field_start:
1200
127k
    case json_tokener_state_object_field_start_after_sep:
1201
127k
      if (c == '}')
1202
19.0k
      {
1203
19.0k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
4
            (tok->flags & JSON_TOKENER_STRICT))
1205
0
        {
1206
0
          tok->err = json_tokener_error_parse_unexpected;
1207
0
          goto out;
1208
0
        }
1209
19.0k
        saved_state = json_tokener_state_finish;
1210
19.0k
        state = json_tokener_state_eatws;
1211
19.0k
      }
1212
108k
      else if (c == '"' || c == '\'')
1213
108k
      {
1214
108k
        tok->quote_char = c;
1215
108k
        printbuf_reset(tok->pb);
1216
108k
        state = json_tokener_state_object_field;
1217
108k
      }
1218
19
      else
1219
19
      {
1220
19
        tok->err = json_tokener_error_parse_object_key_name;
1221
19
        goto out;
1222
19
      }
1223
127k
      break;
1224
1225
127k
    case json_tokener_state_object_field:
1226
116k
    {
1227
      /* Advance until we change state */
1228
116k
      const char *case_start = str;
1229
942k
      while (1)
1230
942k
      {
1231
942k
        if (c == tok->quote_char)
1232
108k
        {
1233
108k
          printbuf_memappend_checked(tok->pb, case_start,
1234
108k
                                     str - case_start);
1235
108k
          obj_field_name = strdup(tok->pb->buf);
1236
108k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
108k
          saved_state = json_tokener_state_object_field_end;
1242
108k
          state = json_tokener_state_eatws;
1243
108k
          break;
1244
108k
        }
1245
833k
        else if (c == '\\')
1246
7.42k
        {
1247
7.42k
          printbuf_memappend_checked(tok->pb, case_start,
1248
7.42k
                                     str - case_start);
1249
7.42k
          saved_state = json_tokener_state_object_field;
1250
7.42k
          state = json_tokener_state_string_escape;
1251
7.42k
          break;
1252
7.42k
        }
1253
826k
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
1254
0
        {
1255
          // Disallow control characters in strict mode
1256
0
          tok->err = json_tokener_error_parse_string;
1257
0
          goto out;
1258
0
        }
1259
826k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
18
        {
1261
18
          printbuf_memappend_checked(tok->pb, case_start,
1262
18
                                     str - case_start);
1263
18
          goto out;
1264
18
        }
1265
826k
      }
1266
116k
    }
1267
116k
    break;
1268
1269
116k
    case json_tokener_state_object_field_end:
1270
108k
      if (c == ':')
1271
108k
      {
1272
108k
        saved_state = json_tokener_state_object_value;
1273
108k
        state = json_tokener_state_eatws;
1274
108k
      }
1275
20
      else
1276
20
      {
1277
20
        tok->err = json_tokener_error_parse_object_key_sep;
1278
20
        goto out;
1279
20
      }
1280
108k
      break;
1281
1282
108k
    case json_tokener_state_object_value:
1283
108k
      if (tok->depth >= tok->max_depth - 1)
1284
0
      {
1285
0
        tok->err = json_tokener_error_depth;
1286
0
        goto out;
1287
0
      }
1288
108k
      state = json_tokener_state_object_value_add;
1289
108k
      tok->depth++;
1290
108k
      json_tokener_reset_level(tok, tok->depth);
1291
108k
      goto redo_char;
1292
1293
108k
    case json_tokener_state_object_value_add:
1294
108k
      if (json_object_object_add(current, obj_field_name, obj) != 0)
1295
0
      {
1296
0
        tok->err = json_tokener_error_memory;
1297
0
        goto out;
1298
0
      }
1299
108k
      free(obj_field_name);
1300
108k
      obj_field_name = NULL;
1301
108k
      saved_state = json_tokener_state_object_sep;
1302
108k
      state = json_tokener_state_eatws;
1303
108k
      goto redo_char;
1304
1305
108k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
108k
      if (c == '}')
1308
29.6k
      {
1309
29.6k
        saved_state = json_tokener_state_finish;
1310
29.6k
        state = json_tokener_state_eatws;
1311
29.6k
      }
1312
78.5k
      else if (c == ',')
1313
78.5k
      {
1314
78.5k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
78.5k
        state = json_tokener_state_eatws;
1316
78.5k
      }
1317
16
      else
1318
16
      {
1319
16
        tok->err = json_tokener_error_parse_object_value_sep;
1320
16
        goto out;
1321
16
      }
1322
108k
      break;
1323
2.06M
    }
1324
811k
    (void)ADVANCE_CHAR(str, tok);
1325
811k
    if (!c) // This is the char *before* advancing
1326
5
      break;
1327
811k
  } /* while(PEEK_CHAR) */
1328
1329
6.76k
out:
1330
6.76k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1331
0
  {
1332
0
    tok->err = json_tokener_error_parse_utf8_string;
1333
0
  }
1334
6.76k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
53
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
53
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
6.76k
  if (!c)
1342
6.50k
  {
1343
    /* We hit an eof char (0) */
1344
6.50k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
183
      tok->err = json_tokener_error_parse_eof;
1346
6.50k
  }
1347
1348
6.76k
#ifdef HAVE_USELOCALE
1349
6.76k
  uselocale(oldlocale);
1350
6.76k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
6.76k
  if (tok->err == json_tokener_success)
1357
6.37k
  {
1358
6.37k
    json_object *ret = json_object_get(current);
1359
6.37k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
12.7k
    for (ii = tok->depth; ii >= 0; ii--)
1363
6.42k
      json_tokener_reset_level(tok, ii);
1364
6.37k
    return ret;
1365
6.37k
  }
1366
1367
396
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
396
           tok->char_offset);
1369
396
  return NULL;
1370
6.76k
}
1371
1372
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes)
1373
0
{
1374
0
  unsigned char chr = c;
1375
0
  if (*nBytes == 0)
1376
0
  {
1377
0
    if (chr >= 0x80)
1378
0
    {
1379
0
      if ((chr & 0xe0) == 0xc0)
1380
0
        *nBytes = 1;
1381
0
      else if ((chr & 0xf0) == 0xe0)
1382
0
        *nBytes = 2;
1383
0
      else if ((chr & 0xf8) == 0xf0)
1384
0
        *nBytes = 3;
1385
0
      else
1386
0
        return 0;
1387
0
    }
1388
0
  }
1389
0
  else
1390
0
  {
1391
0
    if ((chr & 0xC0) != 0x80)
1392
0
      return 0;
1393
0
    (*nBytes)--;
1394
0
  }
1395
0
  return 1;
1396
0
}
1397
1398
void json_tokener_set_flags(struct json_tokener *tok, int flags)
1399
0
{
1400
0
  tok->flags = flags;
1401
0
}
1402
1403
size_t json_tokener_get_parse_end(struct json_tokener *tok)
1404
0
{
1405
0
  assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */
1406
0
  return (size_t)tok->char_offset;
1407
0
}
1408
1409
static int json_tokener_parse_double(const char *buf, int len, double *retval)
1410
607
{
1411
607
  char *end;
1412
607
  *retval = strtod(buf, &end);
1413
607
  if (buf + len == end)
1414
606
    return 0; // It worked
1415
1
  return 1;
1416
607
}