Coverage Report

Created: 2026-01-07 06:10

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
7.89k
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9)
48
49
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
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
898k
{
71
898k
  return c == ' '
72
769k
      || c == '\t'
73
756k
      || c == '\n'
74
753k
      || c == '\r';
75
898k
}
76
77
static inline int is_hex_char(char c)
78
7.90k
{
79
7.90k
  return (c >= '0' && c <= '9')
80
2.56k
      || (c >= 'A' && c <= 'F')
81
275
      || (c >= 'a' && c <= 'f');
82
7.90k
}
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
388
{
134
388
  int jerr_int = (int)jerr;
135
388
  if (jerr_int < 0 ||
136
388
      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
388
  return json_tokener_errors[jerr];
140
388
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
776
{
144
776
  return tok->err;
145
776
}
146
147
/* Stuff for decoding unicode sequences */
148
1.19k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
982
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
231
#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
277k
{
199
277k
  tok->stack[depth].state = json_tokener_state_eatws;
200
277k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
277k
  json_object_put(tok->stack[depth].current);
202
277k
  tok->stack[depth].current = NULL;
203
277k
  free(tok->stack[depth].obj_field_name);
204
277k
  tok->stack[depth].obj_field_name = NULL;
205
277k
}
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
27.8k
  for (i = tok->depth; i >= 0; i--)
214
14.3k
    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
3.68M
#define state tok->stack[tok->depth].state
262
1.44M
#define saved_state tok->stack[tok->depth].saved_state
263
540k
#define current tok->stack[tok->depth].current
264
514k
#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.04M
  (((tok)->char_offset == len)                                         \
286
3.04M
       ? (((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.04M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.04M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.04M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.04M
              : (((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.18M
#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
262k
  do {                                                  \
308
262k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
262k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
262k
  } 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
742k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
742k
  {
395
396
1.89M
  redo_char:
397
1.89M
    switch (state)
398
1.89M
    {
399
400
752k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
897k
      while (is_ws_char(c))
403
144k
      {
404
144k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
144k
      }
407
752k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
939
      {
409
939
        printbuf_reset(tok->pb);
410
939
        printbuf_memappend_checked(tok->pb, &c, 1);
411
939
        state = json_tokener_state_comment_start;
412
939
      }
413
751k
      else
414
751k
      {
415
751k
        state = saved_state;
416
751k
        goto redo_char;
417
751k
      }
418
939
      break;
419
420
135k
    case json_tokener_state_start:
421
135k
      switch (c)
422
135k
      {
423
48.6k
      case '{':
424
48.6k
        state = json_tokener_state_eatws;
425
48.6k
        saved_state = json_tokener_state_object_field_start;
426
48.6k
        current = json_object_new_object();
427
48.6k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
48.6k
        break;
433
48.6k
      case '[':
434
8.78k
        state = json_tokener_state_eatws;
435
8.78k
        saved_state = json_tokener_state_array;
436
8.78k
        current = json_object_new_array();
437
8.78k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
8.78k
        break;
443
8.78k
      case 'I':
444
13
      case 'i':
445
13
        state = json_tokener_state_inf;
446
13
        printbuf_reset(tok->pb);
447
13
        tok->st_pos = 0;
448
13
        goto redo_char;
449
124
      case 'N':
450
253
      case 'n':
451
253
        state = json_tokener_state_null; // or NaN
452
253
        printbuf_reset(tok->pb);
453
253
        tok->st_pos = 0;
454
253
        goto redo_char;
455
46
      case '\'':
456
46
        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
68.3k
      case '"':
464
68.3k
        state = json_tokener_state_string;
465
68.3k
        printbuf_reset(tok->pb);
466
68.3k
        tok->quote_char = c;
467
68.3k
        break;
468
24
      case 'T':
469
56
      case 't':
470
179
      case 'F':
471
310
      case 'f':
472
310
        state = json_tokener_state_boolean;
473
310
        printbuf_reset(tok->pb);
474
310
        tok->st_pos = 0;
475
310
        goto redo_char;
476
1.68k
      case '0':
477
4.03k
      case '1':
478
4.80k
      case '2':
479
5.11k
      case '3':
480
6.13k
      case '4':
481
6.67k
      case '5':
482
6.77k
      case '6':
483
6.90k
      case '7':
484
6.96k
      case '8':
485
7.26k
      case '9':
486
8.91k
      case '-':
487
8.91k
        state = json_tokener_state_number;
488
8.91k
        printbuf_reset(tok->pb);
489
8.91k
        tok->is_double = 0;
490
8.91k
        goto redo_char;
491
84
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
135k
      }
493
125k
      break;
494
495
134k
    case json_tokener_state_finish:
496
134k
      if (tok->depth == 0)
497
6.34k
        goto out;
498
127k
      obj = json_object_get(current);
499
127k
      json_tokener_reset_level(tok, tok->depth);
500
127k
      tok->depth--;
501
127k
      goto redo_char;
502
503
14
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
14
    {
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
14
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
34
      while (tok->st_pos < (int)json_inf_str_len)
516
34
      {
517
34
        char inf_char = *str;
518
34
        if (inf_char != json_inf_str[tok->st_pos] &&
519
28
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
28
              inf_char != json_inf_str_invert[tok->st_pos])
521
34
           )
522
14
        {
523
14
          tok->err = json_tokener_error_parse_unexpected;
524
14
          goto out;
525
14
        }
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.09k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.09k
    {
555
1.09k
      int size;
556
1.09k
      int size_nan;
557
1.09k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.09k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.09k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.09k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.09k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
372
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
718
      {
564
718
        if (tok->st_pos == json_null_str_len)
565
115
        {
566
115
          current = NULL;
567
115
          saved_state = json_tokener_state_finish;
568
115
          state = json_tokener_state_eatws;
569
115
          goto redo_char;
570
115
        }
571
718
      }
572
372
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
372
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
22
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
350
      {
576
350
        if (tok->st_pos == json_nan_str_len)
577
116
        {
578
116
          current = json_object_new_double(NAN);
579
116
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
116
          saved_state = json_tokener_state_finish;
585
116
          state = json_tokener_state_eatws;
586
116
          goto redo_char;
587
116
        }
588
350
      }
589
22
      else
590
22
      {
591
22
        tok->err = json_tokener_error_parse_null;
592
22
        goto out;
593
22
      }
594
837
      tok->st_pos++;
595
837
    }
596
0
    break;
597
598
939
    case json_tokener_state_comment_start:
599
939
      if (c == '*')
600
273
      {
601
273
        state = json_tokener_state_comment;
602
273
      }
603
666
      else if (c == '/')
604
656
      {
605
656
        state = json_tokener_state_comment_eol;
606
656
      }
607
10
      else
608
10
      {
609
10
        tok->err = json_tokener_error_parse_comment;
610
10
        goto out;
611
10
      }
612
929
      printbuf_memappend_checked(tok->pb, &c, 1);
613
929
      break;
614
615
1.37k
    case json_tokener_state_comment:
616
1.37k
    {
617
      /* Advance until we change state */
618
1.37k
      const char *case_start = str;
619
20.1k
      while (c != '*')
620
18.8k
      {
621
18.8k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
23
        {
623
23
          printbuf_memappend_checked(tok->pb, case_start,
624
23
                                     str - case_start);
625
23
          goto out;
626
23
        }
627
18.8k
      }
628
1.35k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.35k
      state = json_tokener_state_comment_end;
630
1.35k
    }
631
0
    break;
632
633
656
    case json_tokener_state_comment_eol:
634
656
    {
635
      /* Advance until we change state */
636
656
      const char *case_start = str;
637
36.4k
      while (c != '\n')
638
35.8k
      {
639
35.8k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
32
        {
641
32
          printbuf_memappend_checked(tok->pb, case_start,
642
32
                                     str - case_start);
643
32
          goto out;
644
32
        }
645
35.8k
      }
646
624
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
624
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
624
      state = json_tokener_state_eatws;
649
624
    }
650
0
    break;
651
652
1.35k
    case json_tokener_state_comment_end:
653
1.35k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.35k
      if (c == '/')
655
246
      {
656
246
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
246
        state = json_tokener_state_eatws;
658
246
      }
659
1.10k
      else
660
1.10k
      {
661
1.10k
        state = json_tokener_state_comment;
662
1.10k
      }
663
1.35k
      break;
664
665
100k
    case json_tokener_state_string:
666
100k
    {
667
      /* Advance until we change state */
668
100k
      const char *case_start = str;
669
1.39M
      while (1)
670
1.39M
      {
671
1.39M
        if (c == tok->quote_char)
672
68.3k
        {
673
68.3k
          printbuf_memappend_checked(tok->pb, case_start,
674
68.3k
                                     str - case_start);
675
68.3k
          current =
676
68.3k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
68.3k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
68.3k
          saved_state = json_tokener_state_finish;
683
68.3k
          state = json_tokener_state_eatws;
684
68.3k
          break;
685
68.3k
        }
686
1.33M
        else if (c == '\\')
687
31.7k
        {
688
31.7k
          printbuf_memappend_checked(tok->pb, case_start,
689
31.7k
                                     str - case_start);
690
31.7k
          saved_state = json_tokener_state_string;
691
31.7k
          state = json_tokener_state_string_escape;
692
31.7k
          break;
693
31.7k
        }
694
1.29M
        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.29M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
42
        {
702
42
          printbuf_memappend_checked(tok->pb, case_start,
703
42
                                     str - case_start);
704
42
          goto out;
705
42
        }
706
1.29M
      }
707
100k
    }
708
100k
    break;
709
710
100k
    case json_tokener_state_string_escape:
711
37.0k
      switch (c)
712
37.0k
      {
713
6.82k
      case '"':
714
22.2k
      case '\\':
715
22.3k
      case '/':
716
22.3k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
22.3k
        state = saved_state;
718
22.3k
        break;
719
444
      case 'b':
720
12.1k
      case 'n':
721
12.4k
      case 'r':
722
12.8k
      case 't':
723
13.0k
      case 'f':
724
13.0k
        if (c == 'b')
725
444
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
12.6k
        else if (c == 'n')
727
11.7k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
898
        else if (c == 'r')
729
266
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
632
        else if (c == 't')
731
444
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
188
        else if (c == 'f')
733
188
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
13.0k
        state = saved_state;
735
13.0k
        break;
736
1.64k
      case 'u':
737
1.64k
        tok->ucs_char = 0;
738
1.64k
        tok->st_pos = 0;
739
1.64k
        state = json_tokener_state_escape_unicode;
740
1.64k
        break;
741
11
      default: tok->err = json_tokener_error_parse_string; goto out;
742
37.0k
      }
743
37.0k
      break;
744
745
      // ===================================================
746
747
37.0k
    case json_tokener_state_escape_unicode:
748
1.98k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
7.90k
      while (1)
751
7.90k
      {
752
7.90k
        if (!c || !is_hex_char(c))
753
16
        {
754
16
          tok->err = json_tokener_error_parse_string;
755
16
          goto out;
756
16
        }
757
7.89k
        tok->ucs_char |=
758
7.89k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
7.89k
        tok->st_pos++;
760
7.89k
        if (tok->st_pos >= 4)
761
1.96k
          break;
762
763
5.92k
        (void)ADVANCE_CHAR(str, tok);
764
5.92k
        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
5.92k
      }
775
1.96k
      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
1.96k
      if (tok->high_surrogate)
781
339
      {
782
339
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
231
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
231
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
231
                                                tok->ucs_char);
787
231
        }
788
108
        else
789
108
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
108
          printbuf_memappend_checked(tok->pb,
794
108
                                     (char *)utf8_replacement_char, 3);
795
108
        }
796
339
        tok->high_surrogate = 0;
797
339
      }
798
799
1.96k
      if (tok->ucs_char < 0x80)
800
741
      {
801
741
        unsigned char unescaped_utf[1];
802
741
        unescaped_utf[0] = tok->ucs_char;
803
741
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
741
      }
805
1.22k
      else if (tok->ucs_char < 0x800)
806
31
      {
807
31
        unsigned char unescaped_utf[2];
808
31
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
31
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
31
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
31
      }
812
1.19k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
552
      {
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
552
        tok->high_surrogate = tok->ucs_char;
829
552
        tok->ucs_char = 0;
830
552
        state = json_tokener_state_escape_unicode_need_escape;
831
552
        break;
832
552
      }
833
643
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
174
      {
835
        /* Got a low surrogate not preceded by a high */
836
174
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
174
      }
838
469
      else if (tok->ucs_char < 0x10000)
839
238
      {
840
238
        unsigned char unescaped_utf[3];
841
238
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
238
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
238
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
238
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
238
      }
846
231
      else if (tok->ucs_char < 0x110000)
847
231
      {
848
231
        unsigned char unescaped_utf[4];
849
231
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
231
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
231
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
231
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
231
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
231
      }
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
1.41k
      state = saved_state; // i.e. _state_string or _state_object_field
861
1.41k
    }
862
0
    break;
863
864
552
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
552
      if (!c || c != '\\')
868
130
      {
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
130
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
130
        tok->high_surrogate = 0;
875
130
        tok->ucs_char = 0;
876
130
        tok->st_pos = 0;
877
130
        state = saved_state;
878
130
        goto redo_char;
879
130
      }
880
422
      state = json_tokener_state_escape_unicode_need_u;
881
422
      break;
882
883
422
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
422
      if (!c || c != 'u')
886
81
      {
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
81
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
81
        tok->high_surrogate = 0;
894
81
        tok->ucs_char = 0;
895
81
        tok->st_pos = 0;
896
81
        state = json_tokener_state_string_escape;
897
81
        goto redo_char;
898
81
      }
899
341
      state = json_tokener_state_escape_unicode;
900
341
      break;
901
902
      // ===================================================
903
904
1.73k
    case json_tokener_state_boolean:
905
1.73k
    {
906
1.73k
      int size1, size2;
907
1.73k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.73k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.73k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.73k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.73k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.51k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
224
      {
914
224
        if (tok->st_pos == json_true_str_len)
915
41
        {
916
41
          current = json_object_new_boolean(1);
917
41
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
41
          saved_state = json_tokener_state_finish;
923
41
          state = json_tokener_state_eatws;
924
41
          goto redo_char;
925
41
        }
926
224
      }
927
1.51k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.51k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
24
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.48k
      {
931
1.48k
        if (tok->st_pos == json_false_str_len)
932
245
        {
933
245
          current = json_object_new_boolean(0);
934
245
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
245
          saved_state = json_tokener_state_finish;
940
245
          state = json_tokener_state_eatws;
941
245
          goto redo_char;
942
245
        }
943
1.48k
      }
944
24
      else
945
24
      {
946
24
        tok->err = json_tokener_error_parse_boolean;
947
24
        goto out;
948
24
      }
949
1.42k
      tok->st_pos++;
950
1.42k
    }
951
0
    break;
952
953
8.91k
    case json_tokener_state_number:
954
8.91k
    {
955
      /* Advance until we change state */
956
8.91k
      const char *case_start = str;
957
8.91k
      int case_len = 0;
958
8.91k
      int is_exponent = 0;
959
8.91k
      int neg_sign_ok = 1;
960
8.91k
      int pos_sign_ok = 0;
961
8.91k
      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
61.4k
      while (c && ((c >= '0' && c <= '9') ||
986
11.6k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
11.2k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
9.24k
                   (!tok->is_double && c == '.')))
989
52.5k
      {
990
52.5k
        pos_sign_ok = neg_sign_ok = 0;
991
52.5k
        ++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
52.5k
        switch (c)
1000
52.5k
        {
1001
372
        case '.':
1002
372
          tok->is_double = 1;
1003
372
          pos_sign_ok = 1;
1004
372
          neg_sign_ok = 1;
1005
372
          break;
1006
357
        case 'e': /* FALLTHRU */
1007
384
        case 'E':
1008
384
          is_exponent = 1;
1009
384
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
384
          pos_sign_ok = neg_sign_ok = 1;
1012
384
          break;
1013
51.7k
        default: break;
1014
52.5k
        }
1015
1016
52.5k
        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
52.5k
      }
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
8.91k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
778
          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
8.87k
      if (case_len > 0)
1037
8.87k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
8.87k
      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
8.87k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
435
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
1.04k
        while (printbuf_length(tok->pb) > 1)
1051
1.02k
        {
1052
1.02k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
1.02k
          if (last_char != 'e' && last_char != 'E' &&
1054
696
              last_char != '-' && last_char != '+')
1055
411
          {
1056
411
            break;
1057
411
          }
1058
610
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
610
          printbuf_length(tok->pb)--;
1060
610
        }
1061
435
      }
1062
8.87k
    }
1063
0
      {
1064
8.87k
        int64_t num64;
1065
8.87k
        uint64_t numuint64;
1066
8.87k
        double numd;
1067
8.87k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
1.29k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
1.29k
        {
1070
1.29k
          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.29k
          current = json_object_new_int64(num64);
1076
1.29k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
1.29k
        }
1082
7.58k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
7.14k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
7.14k
        {
1085
7.14k
          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
7.14k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
1.02k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
7.14k
          if (numuint64 <= INT64_MAX)
1097
6.81k
          {
1098
6.81k
            num64 = (uint64_t)numuint64;
1099
6.81k
            current = json_object_new_int64(num64);
1100
6.81k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
6.81k
          }
1106
329
          else
1107
329
          {
1108
329
            current = json_object_new_uint64(numuint64);
1109
329
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
329
          }
1115
7.14k
        }
1116
440
        else if (tok->is_double &&
1117
435
                 json_tokener_parse_double(
1118
435
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
435
        {
1120
435
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
435
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
435
        }
1127
5
        else
1128
5
        {
1129
5
          tok->err = json_tokener_error_parse_number;
1130
5
          goto out;
1131
5
        }
1132
8.87k
        saved_state = json_tokener_state_finish;
1133
8.87k
        state = json_tokener_state_eatws;
1134
8.87k
        goto redo_char;
1135
8.87k
      }
1136
0
      break;
1137
1138
16.7k
    case json_tokener_state_array_after_sep:
1139
25.5k
    case json_tokener_state_array:
1140
25.5k
      if (c == ']')
1141
158
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
158
        json_object_array_shrink(current, 0);
1144
1145
158
        if (state == json_tokener_state_array_after_sep &&
1146
15
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
158
        saved_state = json_tokener_state_finish;
1152
158
        state = json_tokener_state_eatws;
1153
158
      }
1154
25.3k
      else
1155
25.3k
      {
1156
25.3k
        if (tok->depth >= tok->max_depth - 1)
1157
1
        {
1158
1
          tok->err = json_tokener_error_depth;
1159
1
          goto out;
1160
1
        }
1161
25.3k
        state = json_tokener_state_array_add;
1162
25.3k
        tok->depth++;
1163
25.3k
        json_tokener_reset_level(tok, tok->depth);
1164
25.3k
        goto redo_char;
1165
25.3k
      }
1166
158
      break;
1167
1168
25.1k
    case json_tokener_state_array_add:
1169
25.1k
      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
25.1k
      saved_state = json_tokener_state_array_sep;
1175
25.1k
      state = json_tokener_state_eatws;
1176
25.1k
      goto redo_char;
1177
1178
25.1k
    case json_tokener_state_array_sep:
1179
25.1k
      if (c == ']')
1180
8.32k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
8.32k
        json_object_array_shrink(current, 0);
1183
1184
8.32k
        saved_state = json_tokener_state_finish;
1185
8.32k
        state = json_tokener_state_eatws;
1186
8.32k
      }
1187
16.7k
      else if (c == ',')
1188
16.7k
      {
1189
16.7k
        saved_state = json_tokener_state_array_after_sep;
1190
16.7k
        state = json_tokener_state_eatws;
1191
16.7k
      }
1192
19
      else
1193
19
      {
1194
19
        tok->err = json_tokener_error_parse_array;
1195
19
        goto out;
1196
19
      }
1197
25.0k
      break;
1198
1199
48.6k
    case json_tokener_state_object_field_start:
1200
122k
    case json_tokener_state_object_field_start_after_sep:
1201
122k
      if (c == '}')
1202
19.1k
      {
1203
19.1k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
3
            (tok->flags & JSON_TOKENER_STRICT))
1205
0
        {
1206
0
          tok->err = json_tokener_error_parse_unexpected;
1207
0
          goto out;
1208
0
        }
1209
19.1k
        saved_state = json_tokener_state_finish;
1210
19.1k
        state = json_tokener_state_eatws;
1211
19.1k
      }
1212
103k
      else if (c == '"' || c == '\'')
1213
103k
      {
1214
103k
        tok->quote_char = c;
1215
103k
        printbuf_reset(tok->pb);
1216
103k
        state = json_tokener_state_object_field;
1217
103k
      }
1218
15
      else
1219
15
      {
1220
15
        tok->err = json_tokener_error_parse_object_key_name;
1221
15
        goto out;
1222
15
      }
1223
122k
      break;
1224
1225
122k
    case json_tokener_state_object_field:
1226
108k
    {
1227
      /* Advance until we change state */
1228
108k
      const char *case_start = str;
1229
852k
      while (1)
1230
852k
      {
1231
852k
        if (c == tok->quote_char)
1232
103k
        {
1233
103k
          printbuf_memappend_checked(tok->pb, case_start,
1234
103k
                                     str - case_start);
1235
103k
          obj_field_name = strdup(tok->pb->buf);
1236
103k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
103k
          saved_state = json_tokener_state_object_field_end;
1242
103k
          state = json_tokener_state_eatws;
1243
103k
          break;
1244
103k
        }
1245
749k
        else if (c == '\\')
1246
5.24k
        {
1247
5.24k
          printbuf_memappend_checked(tok->pb, case_start,
1248
5.24k
                                     str - case_start);
1249
5.24k
          saved_state = json_tokener_state_object_field;
1250
5.24k
          state = json_tokener_state_string_escape;
1251
5.24k
          break;
1252
5.24k
        }
1253
743k
        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
743k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
19
        {
1261
19
          printbuf_memappend_checked(tok->pb, case_start,
1262
19
                                     str - case_start);
1263
19
          goto out;
1264
19
        }
1265
743k
      }
1266
108k
    }
1267
108k
    break;
1268
1269
108k
    case json_tokener_state_object_field_end:
1270
103k
      if (c == ':')
1271
103k
      {
1272
103k
        saved_state = json_tokener_state_object_value;
1273
103k
        state = json_tokener_state_eatws;
1274
103k
      }
1275
15
      else
1276
15
      {
1277
15
        tok->err = json_tokener_error_parse_object_key_sep;
1278
15
        goto out;
1279
15
      }
1280
103k
      break;
1281
1282
103k
    case json_tokener_state_object_value:
1283
103k
      if (tok->depth >= tok->max_depth - 1)
1284
0
      {
1285
0
        tok->err = json_tokener_error_depth;
1286
0
        goto out;
1287
0
      }
1288
103k
      state = json_tokener_state_object_value_add;
1289
103k
      tok->depth++;
1290
103k
      json_tokener_reset_level(tok, tok->depth);
1291
103k
      goto redo_char;
1292
1293
102k
    case json_tokener_state_object_value_add:
1294
102k
      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
102k
      free(obj_field_name);
1300
102k
      obj_field_name = NULL;
1301
102k
      saved_state = json_tokener_state_object_sep;
1302
102k
      state = json_tokener_state_eatws;
1303
102k
      goto redo_char;
1304
1305
102k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
102k
      if (c == '}')
1308
28.9k
      {
1309
28.9k
        saved_state = json_tokener_state_finish;
1310
28.9k
        state = json_tokener_state_eatws;
1311
28.9k
      }
1312
73.8k
      else if (c == ',')
1313
73.7k
      {
1314
73.7k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
73.7k
        state = json_tokener_state_eatws;
1316
73.7k
      }
1317
20
      else
1318
20
      {
1319
20
        tok->err = json_tokener_error_parse_object_value_sep;
1320
20
        goto out;
1321
20
      }
1322
102k
      break;
1323
1.89M
    }
1324
735k
    (void)ADVANCE_CHAR(str, tok);
1325
735k
    if (!c) // This is the char *before* advancing
1326
4
      break;
1327
735k
  } /* 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
52
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
52
          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
179
      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.41k
      json_tokener_reset_level(tok, ii);
1364
6.37k
    return ret;
1365
6.37k
  }
1366
1367
387
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
387
           tok->char_offset);
1369
387
  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
435
{
1411
435
  char *end;
1412
435
  *retval = strtod(buf, &end);
1413
435
  if (buf + len == end)
1414
435
    return 0; // It worked
1415
0
  return 1;
1416
435
}