Coverage Report

Created: 2026-02-22 06:11

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
10.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
838k
{
71
838k
  return c == ' '
72
694k
      || c == '\t'
73
674k
      || c == '\n'
74
671k
      || c == '\r';
75
838k
}
76
77
static inline int is_hex_char(char c)
78
10.6k
{
79
10.6k
  return (c >= '0' && c <= '9')
80
3.56k
      || (c >= 'A' && c <= 'F')
81
226
      || (c >= 'a' && c <= 'f');
82
10.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
366
{
134
366
  int jerr_int = (int)jerr;
135
366
  if (jerr_int < 0 ||
136
366
      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
366
  return json_tokener_errors[jerr];
140
366
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
732
{
144
732
  return tok->err;
145
732
}
146
147
/* Stuff for decoding unicode sequences */
148
1.83k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.57k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
274
#define DECODE_SURROGATE_PAIR(hi, lo) ((((hi)&0x3FF) << 10) + ((lo)&0x3FF) + 0x10000)
151
static unsigned char utf8_replacement_char[3] = {0xEF, 0xBF, 0xBD};
152
153
struct json_tokener *json_tokener_new_ex(int depth)
154
5.54k
{
155
5.54k
  struct json_tokener *tok;
156
157
5.54k
  if (depth < 1)
158
0
    return NULL;
159
160
5.54k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
5.54k
  if (!tok)
162
0
    return NULL;
163
5.54k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
5.54k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
5.54k
  tok->pb = printbuf_new();
170
5.54k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
5.54k
  tok->max_depth = depth;
177
5.54k
  json_tokener_reset(tok);
178
5.54k
  return tok;
179
5.54k
}
180
181
struct json_tokener *json_tokener_new(void)
182
5.54k
{
183
5.54k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
5.54k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
5.54k
{
188
5.54k
  if (!tok)
189
0
    return;
190
5.54k
  json_tokener_reset(tok);
191
5.54k
  if (tok->pb)
192
5.54k
    printbuf_free(tok->pb);
193
5.54k
  free(tok->stack);
194
5.54k
  free(tok);
195
5.54k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
248k
{
199
248k
  tok->stack[depth].state = json_tokener_state_eatws;
200
248k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
248k
  json_object_put(tok->stack[depth].current);
202
248k
  tok->stack[depth].current = NULL;
203
248k
  free(tok->stack[depth].obj_field_name);
204
248k
  tok->stack[depth].obj_field_name = NULL;
205
248k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
11.0k
{
209
11.0k
  int i;
210
11.0k
  if (!tok)
211
0
    return;
212
213
23.0k
  for (i = tok->depth; i >= 0; i--)
214
11.9k
    json_tokener_reset_level(tok, i);
215
11.0k
  tok->depth = 0;
216
11.0k
  tok->err = json_tokener_success;
217
11.0k
}
218
219
struct json_object *json_tokener_parse(const char *str)
220
0
{
221
0
  enum json_tokener_error jerr_ignored;
222
0
  struct json_object *obj;
223
0
  obj = json_tokener_parse_verbose(str, &jerr_ignored);
224
0
  return obj;
225
0
}
226
227
struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
228
0
{
229
0
  struct json_tokener *tok;
230
0
  struct json_object *obj;
231
232
0
  tok = json_tokener_new();
233
0
  if (!tok)
234
0
  {
235
0
    *error = json_tokener_error_memory;
236
0
    return NULL;
237
0
  }
238
0
  obj = json_tokener_parse_ex(tok, str, -1);
239
0
  *error = tok->err;
240
0
  if (tok->err != json_tokener_success
241
#if 0
242
    /* This would be a more sensible default, and cause parsing
243
     * things like "null123" to fail when the caller can't know
244
     * where the parsing left off, but starting to fail would
245
     * be a notable behaviour change.  Save for a 1.0 release.
246
     */
247
      || json_tokener_get_parse_end(tok) != strlen(str)
248
#endif
249
0
  )
250
251
0
  {
252
0
    if (obj != NULL)
253
0
      json_object_put(obj);
254
0
    obj = NULL;
255
0
  }
256
257
0
  json_tokener_free(tok);
258
0
  return obj;
259
0
}
260
261
3.35M
#define state tok->stack[tok->depth].state
262
1.31M
#define saved_state tok->stack[tok->depth].saved_state
263
486k
#define current tok->stack[tok->depth].current
264
450k
#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.05M
  (((tok)->char_offset == len)                                         \
286
3.05M
       ? (((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.05M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.05M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.05M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.05M
              : (((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.23M
#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
266k
  do {                                                  \
308
266k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
266k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
266k
  } while (0)
314
315
/* End optimization macro defs */
316
317
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
318
5.54k
{
319
5.54k
  struct json_object *obj = NULL;
320
5.54k
  char c = '\1';
321
5.54k
  unsigned int nBytes = 0;
322
5.54k
  unsigned int *nBytesp = &nBytes;
323
324
5.54k
#ifdef HAVE_USELOCALE
325
5.54k
  locale_t oldlocale = uselocale(NULL);
326
5.54k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
5.54k
  tok->char_offset = 0;
332
5.54k
  tok->err = json_tokener_success;
333
334
  /* this interface is presently not 64-bit clean due to the int len argument
335
   * and the internal printbuf interface that takes 32-bit int len arguments
336
   * so the function limits the maximum string size to INT32_MAX (2GB).
337
   * If the function is called with len == -1 then strlen is called to check
338
   * the string length is less than INT32_MAX (2GB)
339
   */
340
5.54k
  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX))
341
0
  {
342
0
    tok->err = json_tokener_error_size;
343
0
    return NULL;
344
0
  }
345
346
5.54k
#ifdef HAVE_USELOCALE
347
5.54k
  {
348
5.54k
#ifdef HAVE_DUPLOCALE
349
5.54k
    locale_t duploc = duplocale(oldlocale);
350
5.54k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
5.54k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
5.54k
    if (newloc == NULL)
360
0
    {
361
0
      tok->err = json_tokener_error_memory;
362
0
#ifdef HAVE_DUPLOCALE
363
0
      freelocale(duploc);
364
0
#endif
365
0
      return NULL;
366
0
    }
367
#ifdef NEWLOCALE_NEEDS_FREELOCALE
368
#ifdef HAVE_DUPLOCALE
369
    // Older versions of FreeBSD (<12.4) don't free the locale
370
    // passed to newlocale(), so do it here
371
    freelocale(duploc);
372
#endif
373
#endif
374
5.54k
    uselocale(newloc);
375
5.54k
  }
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
687k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
687k
  {
395
396
1.72M
  redo_char:
397
1.72M
    switch (state)
398
1.72M
    {
399
400
671k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
837k
      while (is_ws_char(c))
403
166k
      {
404
166k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
166k
      }
407
671k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
999
      {
409
999
        printbuf_reset(tok->pb);
410
999
        printbuf_memappend_checked(tok->pb, &c, 1);
411
999
        state = json_tokener_state_comment_start;
412
999
      }
413
670k
      else
414
670k
      {
415
670k
        state = saved_state;
416
670k
        goto redo_char;
417
670k
      }
418
999
      break;
419
420
121k
    case json_tokener_state_start:
421
121k
      switch (c)
422
121k
      {
423
40.6k
      case '{':
424
40.6k
        state = json_tokener_state_eatws;
425
40.6k
        saved_state = json_tokener_state_object_field_start;
426
40.6k
        current = json_object_new_object();
427
40.6k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
40.6k
        break;
433
40.6k
      case '[':
434
8.07k
        state = json_tokener_state_eatws;
435
8.07k
        saved_state = json_tokener_state_array;
436
8.07k
        current = json_object_new_array();
437
8.07k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
8.07k
        break;
443
8.07k
      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
135
      case 'N':
450
316
      case 'n':
451
316
        state = json_tokener_state_null; // or NaN
452
316
        printbuf_reset(tok->pb);
453
316
        tok->st_pos = 0;
454
316
        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
62.2k
      case '"':
464
62.2k
        state = json_tokener_state_string;
465
62.2k
        printbuf_reset(tok->pb);
466
62.2k
        tok->quote_char = c;
467
62.2k
        break;
468
22
      case 'T':
469
68
      case 't':
470
196
      case 'F':
471
304
      case 'f':
472
304
        state = json_tokener_state_boolean;
473
304
        printbuf_reset(tok->pb);
474
304
        tok->st_pos = 0;
475
304
        goto redo_char;
476
2.21k
      case '0':
477
4.47k
      case '1':
478
5.32k
      case '2':
479
5.67k
      case '3':
480
6.94k
      case '4':
481
7.54k
      case '5':
482
7.66k
      case '6':
483
7.80k
      case '7':
484
7.86k
      case '8':
485
8.17k
      case '9':
486
9.99k
      case '-':
487
9.99k
        state = json_tokener_state_number;
488
9.99k
        printbuf_reset(tok->pb);
489
9.99k
        tok->is_double = 0;
490
9.99k
        goto redo_char;
491
65
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
121k
      }
493
111k
      break;
494
495
120k
    case json_tokener_state_finish:
496
120k
      if (tok->depth == 0)
497
5.14k
        goto out;
498
115k
      obj = json_object_get(current);
499
115k
      json_tokener_reset_level(tok, tok->depth);
500
115k
      tok->depth--;
501
115k
      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.40k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.40k
    {
555
1.40k
      int size;
556
1.40k
      int size_nan;
557
1.40k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.40k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.40k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.40k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.40k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
411
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
994
      {
564
994
        if (tok->st_pos == json_null_str_len)
565
168
        {
566
168
          current = NULL;
567
168
          saved_state = json_tokener_state_finish;
568
168
          state = json_tokener_state_eatws;
569
168
          goto redo_char;
570
168
        }
571
994
      }
572
411
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
411
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
18
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
393
      {
576
393
        if (tok->st_pos == json_nan_str_len)
577
130
        {
578
130
          current = json_object_new_double(NAN);
579
130
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
130
          saved_state = json_tokener_state_finish;
585
130
          state = json_tokener_state_eatws;
586
130
          goto redo_char;
587
130
        }
588
393
      }
589
18
      else
590
18
      {
591
18
        tok->err = json_tokener_error_parse_null;
592
18
        goto out;
593
18
      }
594
1.08k
      tok->st_pos++;
595
1.08k
    }
596
0
    break;
597
598
999
    case json_tokener_state_comment_start:
599
999
      if (c == '*')
600
297
      {
601
297
        state = json_tokener_state_comment;
602
297
      }
603
702
      else if (c == '/')
604
690
      {
605
690
        state = json_tokener_state_comment_eol;
606
690
      }
607
12
      else
608
12
      {
609
12
        tok->err = json_tokener_error_parse_comment;
610
12
        goto out;
611
12
      }
612
987
      printbuf_memappend_checked(tok->pb, &c, 1);
613
987
      break;
614
615
1.65k
    case json_tokener_state_comment:
616
1.65k
    {
617
      /* Advance until we change state */
618
1.65k
      const char *case_start = str;
619
23.4k
      while (c != '*')
620
21.8k
      {
621
21.8k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
26
        {
623
26
          printbuf_memappend_checked(tok->pb, case_start,
624
26
                                     str - case_start);
625
26
          goto out;
626
26
        }
627
21.8k
      }
628
1.63k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.63k
      state = json_tokener_state_comment_end;
630
1.63k
    }
631
0
    break;
632
633
690
    case json_tokener_state_comment_eol:
634
690
    {
635
      /* Advance until we change state */
636
690
      const char *case_start = str;
637
41.0k
      while (c != '\n')
638
40.4k
      {
639
40.4k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
37
        {
641
37
          printbuf_memappend_checked(tok->pb, case_start,
642
37
                                     str - case_start);
643
37
          goto out;
644
37
        }
645
40.4k
      }
646
653
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
653
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
653
      state = json_tokener_state_eatws;
649
653
    }
650
0
    break;
651
652
1.63k
    case json_tokener_state_comment_end:
653
1.63k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.63k
      if (c == '/')
655
267
      {
656
267
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
267
        state = json_tokener_state_eatws;
658
267
      }
659
1.36k
      else
660
1.36k
      {
661
1.36k
        state = json_tokener_state_comment;
662
1.36k
      }
663
1.63k
      break;
664
665
102k
    case json_tokener_state_string:
666
102k
    {
667
      /* Advance until we change state */
668
102k
      const char *case_start = str;
669
1.47M
      while (1)
670
1.47M
      {
671
1.47M
        if (c == tok->quote_char)
672
62.2k
        {
673
62.2k
          printbuf_memappend_checked(tok->pb, case_start,
674
62.2k
                                     str - case_start);
675
62.2k
          current =
676
62.2k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
62.2k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
62.2k
          saved_state = json_tokener_state_finish;
683
62.2k
          state = json_tokener_state_eatws;
684
62.2k
          break;
685
62.2k
        }
686
1.41M
        else if (c == '\\')
687
39.7k
        {
688
39.7k
          printbuf_memappend_checked(tok->pb, case_start,
689
39.7k
                                     str - case_start);
690
39.7k
          saved_state = json_tokener_state_string;
691
39.7k
          state = json_tokener_state_string_escape;
692
39.7k
          break;
693
39.7k
        }
694
1.37M
        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.37M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
36
        {
702
36
          printbuf_memappend_checked(tok->pb, case_start,
703
36
                                     str - case_start);
704
36
          goto out;
705
36
        }
706
1.37M
      }
707
102k
    }
708
101k
    break;
709
710
101k
    case json_tokener_state_string_escape:
711
47.3k
      switch (c)
712
47.3k
      {
713
9.05k
      case '"':
714
27.6k
      case '\\':
715
27.7k
      case '/':
716
27.7k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
27.7k
        state = saved_state;
718
27.7k
        break;
719
741
      case 'b':
720
16.2k
      case 'n':
721
16.4k
      case 'r':
722
17.0k
      case 't':
723
17.2k
      case 'f':
724
17.2k
        if (c == 'b')
725
741
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
16.5k
        else if (c == 'n')
727
15.4k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.05k
        else if (c == 'r')
729
276
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
779
        else if (c == 't')
731
548
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
231
        else if (c == 'f')
733
231
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
17.2k
        state = saved_state;
735
17.2k
        break;
736
2.26k
      case 'u':
737
2.26k
        tok->ucs_char = 0;
738
2.26k
        tok->st_pos = 0;
739
2.26k
        state = json_tokener_state_escape_unicode;
740
2.26k
        break;
741
11
      default: tok->err = json_tokener_error_parse_string; goto out;
742
47.3k
      }
743
47.3k
      break;
744
745
      // ===================================================
746
747
47.3k
    case json_tokener_state_escape_unicode:
748
2.67k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
10.6k
      while (1)
751
10.6k
      {
752
10.6k
        if (!c || !is_hex_char(c))
753
12
        {
754
12
          tok->err = json_tokener_error_parse_string;
755
12
          goto out;
756
12
        }
757
10.6k
        tok->ucs_char |=
758
10.6k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
10.6k
        tok->st_pos++;
760
10.6k
        if (tok->st_pos >= 4)
761
2.66k
          break;
762
763
8.00k
        (void)ADVANCE_CHAR(str, tok);
764
8.00k
        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.00k
      }
775
2.66k
      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.66k
      if (tok->high_surrogate)
781
403
      {
782
403
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
274
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
274
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
274
                                                tok->ucs_char);
787
274
        }
788
129
        else
789
129
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
129
          printbuf_memappend_checked(tok->pb,
794
129
                                     (char *)utf8_replacement_char, 3);
795
129
        }
796
403
        tok->high_surrogate = 0;
797
403
      }
798
799
2.66k
      if (tok->ucs_char < 0x80)
800
786
      {
801
786
        unsigned char unescaped_utf[1];
802
786
        unescaped_utf[0] = tok->ucs_char;
803
786
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
786
      }
805
1.87k
      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.83k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
656
      {
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
656
        tok->high_surrogate = tok->ucs_char;
829
656
        tok->ucs_char = 0;
830
656
        state = json_tokener_state_escape_unicode_need_escape;
831
656
        break;
832
656
      }
833
1.17k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
417
      {
835
        /* Got a low surrogate not preceded by a high */
836
417
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
417
      }
838
759
      else if (tok->ucs_char < 0x10000)
839
485
      {
840
485
        unsigned char unescaped_utf[3];
841
485
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
485
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
485
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
485
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
485
      }
846
274
      else if (tok->ucs_char < 0x110000)
847
274
      {
848
274
        unsigned char unescaped_utf[4];
849
274
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
274
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
274
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
274
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
274
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
274
      }
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.00k
      state = saved_state; // i.e. _state_string or _state_object_field
861
2.00k
    }
862
0
    break;
863
864
656
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
656
      if (!c || c != '\\')
868
156
      {
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
156
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
156
        tok->high_surrogate = 0;
875
156
        tok->ucs_char = 0;
876
156
        tok->st_pos = 0;
877
156
        state = saved_state;
878
156
        goto redo_char;
879
156
      }
880
500
      state = json_tokener_state_escape_unicode_need_u;
881
500
      break;
882
883
500
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
500
      if (!c || c != 'u')
886
95
      {
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
95
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
95
        tok->high_surrogate = 0;
894
95
        tok->ucs_char = 0;
895
95
        tok->st_pos = 0;
896
95
        state = json_tokener_state_string_escape;
897
95
        goto redo_char;
898
95
      }
899
405
      state = json_tokener_state_escape_unicode;
900
405
      break;
901
902
      // ===================================================
903
904
1.68k
    case json_tokener_state_boolean:
905
1.68k
    {
906
1.68k
      int size1, size2;
907
1.68k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.68k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.68k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.68k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.68k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.40k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
284
      {
914
284
        if (tok->st_pos == json_true_str_len)
915
53
        {
916
53
          current = json_object_new_boolean(1);
917
53
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
53
          saved_state = json_tokener_state_finish;
923
53
          state = json_tokener_state_eatws;
924
53
          goto redo_char;
925
53
        }
926
284
      }
927
1.40k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.40k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
25
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.37k
      {
931
1.37k
        if (tok->st_pos == json_false_str_len)
932
226
        {
933
226
          current = json_object_new_boolean(0);
934
226
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
226
          saved_state = json_tokener_state_finish;
940
226
          state = json_tokener_state_eatws;
941
226
          goto redo_char;
942
226
        }
943
1.37k
      }
944
25
      else
945
25
      {
946
25
        tok->err = json_tokener_error_parse_boolean;
947
25
        goto out;
948
25
      }
949
1.38k
      tok->st_pos++;
950
1.38k
    }
951
0
    break;
952
953
9.99k
    case json_tokener_state_number:
954
9.99k
    {
955
      /* Advance until we change state */
956
9.99k
      const char *case_start = str;
957
9.99k
      int case_len = 0;
958
9.99k
      int is_exponent = 0;
959
9.99k
      int neg_sign_ok = 1;
960
9.99k
      int pos_sign_ok = 0;
961
9.99k
      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
70.1k
      while (c && ((c >= '0' && c <= '9') ||
986
12.9k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
12.5k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
10.3k
                   (!tok->is_double && c == '.')))
989
60.1k
      {
990
60.1k
        pos_sign_ok = neg_sign_ok = 0;
991
60.1k
        ++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
60.1k
        switch (c)
1000
60.1k
        {
1001
401
        case '.':
1002
401
          tok->is_double = 1;
1003
401
          pos_sign_ok = 1;
1004
401
          neg_sign_ok = 1;
1005
401
          break;
1006
386
        case 'e': /* FALLTHRU */
1007
416
        case 'E':
1008
416
          is_exponent = 1;
1009
416
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
416
          pos_sign_ok = neg_sign_ok = 1;
1012
416
          break;
1013
59.3k
        default: break;
1014
60.1k
        }
1015
1016
60.1k
        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
60.1k
      }
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
9.99k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
826
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
37
      {
1033
37
        tok->err = json_tokener_error_parse_number;
1034
37
        goto out;
1035
37
      }
1036
9.96k
      if (case_len > 0)
1037
9.96k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
9.96k
      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
9.96k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
469
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
1.12k
        while (printbuf_length(tok->pb) > 1)
1051
1.10k
        {
1052
1.10k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
1.10k
          if (last_char != 'e' && last_char != 'E' &&
1054
751
              last_char != '-' && last_char != '+')
1055
447
          {
1056
447
            break;
1057
447
          }
1058
653
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
653
          printbuf_length(tok->pb)--;
1060
653
        }
1061
469
      }
1062
9.96k
    }
1063
0
      {
1064
9.96k
        int64_t num64;
1065
9.96k
        uint64_t numuint64;
1066
9.96k
        double numd;
1067
9.96k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
1.43k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
1.43k
        {
1070
1.43k
          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.43k
          current = json_object_new_int64(num64);
1076
1.43k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
1.43k
        }
1082
8.52k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
8.05k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
8.05k
        {
1085
8.05k
          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
8.05k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
1.47k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
8.05k
          if (numuint64 <= INT64_MAX)
1097
7.70k
          {
1098
7.70k
            num64 = (uint64_t)numuint64;
1099
7.70k
            current = json_object_new_int64(num64);
1100
7.70k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
7.70k
          }
1106
345
          else
1107
345
          {
1108
345
            current = json_object_new_uint64(numuint64);
1109
345
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
345
          }
1115
8.05k
        }
1116
473
        else if (tok->is_double &&
1117
469
                 json_tokener_parse_double(
1118
469
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
468
        {
1120
468
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
468
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
468
        }
1127
5
        else
1128
5
        {
1129
5
          tok->err = json_tokener_error_parse_number;
1130
5
          goto out;
1131
5
        }
1132
9.95k
        saved_state = json_tokener_state_finish;
1133
9.95k
        state = json_tokener_state_eatws;
1134
9.95k
        goto redo_char;
1135
9.96k
      }
1136
0
      break;
1137
1138
17.9k
    case json_tokener_state_array_after_sep:
1139
25.9k
    case json_tokener_state_array:
1140
25.9k
      if (c == ']')
1141
189
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
189
        json_object_array_shrink(current, 0);
1144
1145
189
        if (state == json_tokener_state_array_after_sep &&
1146
18
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
189
        saved_state = json_tokener_state_finish;
1152
189
        state = json_tokener_state_eatws;
1153
189
      }
1154
25.7k
      else
1155
25.7k
      {
1156
25.7k
        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.7k
        state = json_tokener_state_array_add;
1162
25.7k
        tok->depth++;
1163
25.7k
        json_tokener_reset_level(tok, tok->depth);
1164
25.7k
        goto redo_char;
1165
25.7k
      }
1166
189
      break;
1167
1168
25.4k
    case json_tokener_state_array_add:
1169
25.4k
      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.4k
      saved_state = json_tokener_state_array_sep;
1175
25.4k
      state = json_tokener_state_eatws;
1176
25.4k
      goto redo_char;
1177
1178
25.4k
    case json_tokener_state_array_sep:
1179
25.4k
      if (c == ']')
1180
7.52k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
7.52k
        json_object_array_shrink(current, 0);
1183
1184
7.52k
        saved_state = json_tokener_state_finish;
1185
7.52k
        state = json_tokener_state_eatws;
1186
7.52k
      }
1187
17.9k
      else if (c == ',')
1188
17.9k
      {
1189
17.9k
        saved_state = json_tokener_state_array_after_sep;
1190
17.9k
        state = json_tokener_state_eatws;
1191
17.9k
      }
1192
22
      else
1193
22
      {
1194
22
        tok->err = json_tokener_error_parse_array;
1195
22
        goto out;
1196
22
      }
1197
25.4k
      break;
1198
1199
40.6k
    case json_tokener_state_object_field_start:
1200
106k
    case json_tokener_state_object_field_start_after_sep:
1201
106k
      if (c == '}')
1202
15.4k
      {
1203
15.4k
        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
15.4k
        saved_state = json_tokener_state_finish;
1210
15.4k
        state = json_tokener_state_eatws;
1211
15.4k
      }
1212
90.5k
      else if (c == '"' || c == '\'')
1213
90.5k
      {
1214
90.5k
        tok->quote_char = c;
1215
90.5k
        printbuf_reset(tok->pb);
1216
90.5k
        state = json_tokener_state_object_field;
1217
90.5k
      }
1218
16
      else
1219
16
      {
1220
16
        tok->err = json_tokener_error_parse_object_key_name;
1221
16
        goto out;
1222
16
      }
1223
105k
      break;
1224
1225
105k
    case json_tokener_state_object_field:
1226
97.9k
    {
1227
      /* Advance until we change state */
1228
97.9k
      const char *case_start = str;
1229
795k
      while (1)
1230
795k
      {
1231
795k
        if (c == tok->quote_char)
1232
90.4k
        {
1233
90.4k
          printbuf_memappend_checked(tok->pb, case_start,
1234
90.4k
                                     str - case_start);
1235
90.4k
          obj_field_name = strdup(tok->pb->buf);
1236
90.4k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
90.4k
          saved_state = json_tokener_state_object_field_end;
1242
90.4k
          state = json_tokener_state_eatws;
1243
90.4k
          break;
1244
90.4k
        }
1245
704k
        else if (c == '\\')
1246
7.49k
        {
1247
7.49k
          printbuf_memappend_checked(tok->pb, case_start,
1248
7.49k
                                     str - case_start);
1249
7.49k
          saved_state = json_tokener_state_object_field;
1250
7.49k
          state = json_tokener_state_string_escape;
1251
7.49k
          break;
1252
7.49k
        }
1253
697k
        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
697k
        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
697k
      }
1266
97.9k
    }
1267
97.9k
    break;
1268
1269
97.9k
    case json_tokener_state_object_field_end:
1270
90.4k
      if (c == ':')
1271
90.4k
      {
1272
90.4k
        saved_state = json_tokener_state_object_value;
1273
90.4k
        state = json_tokener_state_eatws;
1274
90.4k
      }
1275
20
      else
1276
20
      {
1277
20
        tok->err = json_tokener_error_parse_object_key_sep;
1278
20
        goto out;
1279
20
      }
1280
90.4k
      break;
1281
1282
90.4k
    case json_tokener_state_object_value:
1283
90.4k
      if (tok->depth >= tok->max_depth - 1)
1284
0
      {
1285
0
        tok->err = json_tokener_error_depth;
1286
0
        goto out;
1287
0
      }
1288
90.4k
      state = json_tokener_state_object_value_add;
1289
90.4k
      tok->depth++;
1290
90.4k
      json_tokener_reset_level(tok, tok->depth);
1291
90.4k
      goto redo_char;
1292
1293
89.9k
    case json_tokener_state_object_value_add:
1294
89.9k
      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
89.9k
      free(obj_field_name);
1300
89.9k
      obj_field_name = NULL;
1301
89.9k
      saved_state = json_tokener_state_object_sep;
1302
89.9k
      state = json_tokener_state_eatws;
1303
89.9k
      goto redo_char;
1304
1305
89.9k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
89.9k
      if (c == '}')
1308
24.5k
      {
1309
24.5k
        saved_state = json_tokener_state_finish;
1310
24.5k
        state = json_tokener_state_eatws;
1311
24.5k
      }
1312
65.3k
      else if (c == ',')
1313
65.3k
      {
1314
65.3k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
65.3k
        state = json_tokener_state_eatws;
1316
65.3k
      }
1317
17
      else
1318
17
      {
1319
17
        tok->err = json_tokener_error_parse_object_value_sep;
1320
17
        goto out;
1321
17
      }
1322
89.8k
      break;
1323
1.72M
    }
1324
682k
    (void)ADVANCE_CHAR(str, tok);
1325
682k
    if (!c) // This is the char *before* advancing
1326
4
      break;
1327
682k
  } /* while(PEEK_CHAR) */
1328
1329
5.54k
out:
1330
5.54k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1331
0
  {
1332
0
    tok->err = json_tokener_error_parse_utf8_string;
1333
0
  }
1334
5.54k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
56
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
56
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
5.54k
  if (!c)
1342
5.28k
  {
1343
    /* We hit an eof char (0) */
1344
5.28k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
161
      tok->err = json_tokener_error_parse_eof;
1346
5.28k
  }
1347
1348
5.54k
#ifdef HAVE_USELOCALE
1349
5.54k
  uselocale(oldlocale);
1350
5.54k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
5.54k
  if (tok->err == json_tokener_success)
1357
5.17k
  {
1358
5.17k
    json_object *ret = json_object_get(current);
1359
5.17k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
10.3k
    for (ii = tok->depth; ii >= 0; ii--)
1363
5.21k
      json_tokener_reset_level(tok, ii);
1364
5.17k
    return ret;
1365
5.17k
  }
1366
1367
365
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
365
           tok->char_offset);
1369
365
  return NULL;
1370
5.54k
}
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
469
{
1411
469
  char *end;
1412
469
  *retval = strtod(buf, &end);
1413
469
  if (buf + len == end)
1414
468
    return 0; // It worked
1415
1
  return 1;
1416
469
}