Coverage Report

Created: 2026-01-09 07:00

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
19.2k
#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
1.65M
{
71
1.65M
  return c == ' '
72
1.52M
      || c == '\t'
73
1.50M
      || c == '\n'
74
1.50M
      || c == '\r';
75
1.65M
}
76
77
static inline int is_hex_char(char c)
78
19.3k
{
79
19.3k
  return (c >= '0' && c <= '9')
80
8.30k
      || (c >= 'A' && c <= 'F')
81
1.76k
      || (c >= 'a' && c <= 'f');
82
19.3k
}
83
84
/* Use C99 NAN by default; if not available, nan("") should work too. */
85
#ifndef NAN
86
#define NAN nan("")
87
#endif /* !NAN */
88
89
static const char json_null_str[] = "null";
90
static const int json_null_str_len = sizeof(json_null_str) - 1;
91
static const char json_inf_str[] = "Infinity";
92
/* Swapped case "Infinity" to avoid need to call tolower() on input chars: */
93
static const char json_inf_str_invert[] = "iNFINITY";
94
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
95
static const char json_nan_str[] = "NaN";
96
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
97
static const char json_true_str[] = "true";
98
static const int json_true_str_len = sizeof(json_true_str) - 1;
99
static const char json_false_str[] = "false";
100
static const int json_false_str_len = sizeof(json_false_str) - 1;
101
102
/* clang-format off */
103
static const char *json_tokener_errors[] = {
104
  "success",
105
  "continue",
106
  "nesting too deep",
107
  "unexpected end of data",
108
  "unexpected character",
109
  "null expected",
110
  "boolean expected",
111
  "number expected",
112
  "array value separator ',' expected",
113
  "quoted object property name expected",
114
  "object property name separator ':' expected",
115
  "object value separator ',' expected",
116
  "invalid string sequence",
117
  "expected comment",
118
  "invalid utf-8 string",
119
  "buffer size overflow",
120
  "out of memory"
121
};
122
/* clang-format on */
123
124
/**
125
 * validete the utf-8 string in strict model.
126
 * if not utf-8 format, return err.
127
 */
128
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes);
129
130
static int json_tokener_parse_double(const char *buf, int len, double *retval);
131
132
const char *json_tokener_error_desc(enum json_tokener_error jerr)
133
2.27k
{
134
2.27k
  int jerr_int = (int)jerr;
135
2.27k
  if (jerr_int < 0 ||
136
2.27k
      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
2.27k
  return json_tokener_errors[jerr];
140
2.27k
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
4.55k
{
144
4.55k
  return tok->err;
145
4.55k
}
146
147
/* Stuff for decoding unicode sequences */
148
3.47k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
2.73k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
522
#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
9.78k
{
155
9.78k
  struct json_tokener *tok;
156
157
9.78k
  if (depth < 1)
158
0
    return NULL;
159
160
9.78k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
9.78k
  if (!tok)
162
0
    return NULL;
163
9.78k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
9.78k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
9.78k
  tok->pb = printbuf_new();
170
9.78k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
9.78k
  tok->max_depth = depth;
177
9.78k
  json_tokener_reset(tok);
178
9.78k
  return tok;
179
9.78k
}
180
181
struct json_tokener *json_tokener_new(void)
182
9.78k
{
183
9.78k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
9.78k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
9.78k
{
188
9.78k
  if (!tok)
189
0
    return;
190
9.78k
  json_tokener_reset(tok);
191
9.78k
  if (tok->pb)
192
9.78k
    printbuf_free(tok->pb);
193
9.78k
  free(tok->stack);
194
9.78k
  free(tok);
195
9.78k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
643k
{
199
643k
  tok->stack[depth].state = json_tokener_state_eatws;
200
643k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
643k
  json_object_put(tok->stack[depth].current);
202
643k
  tok->stack[depth].current = NULL;
203
643k
  free(tok->stack[depth].obj_field_name);
204
643k
  tok->stack[depth].obj_field_name = NULL;
205
643k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
19.5k
{
209
19.5k
  int i;
210
19.5k
  if (!tok)
211
0
    return;
212
213
42.7k
  for (i = tok->depth; i >= 0; i--)
214
23.1k
    json_tokener_reset_level(tok, i);
215
19.5k
  tok->depth = 0;
216
19.5k
  tok->err = json_tokener_success;
217
19.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
7.34M
#define state tok->stack[tok->depth].state
262
2.76M
#define saved_state tok->stack[tok->depth].saved_state
263
1.24M
#define current tok->stack[tok->depth].current
264
587k
#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
5.56M
  (((tok)->char_offset == len)                                         \
286
5.56M
       ? (((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
5.56M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
5.56M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
5.56M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
5.56M
              : (((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
9.89M
#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
531k
  do {                                                  \
308
531k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
531k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
531k
  } 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
9.78k
{
319
9.78k
  struct json_object *obj = NULL;
320
9.78k
  char c = '\1';
321
9.78k
  unsigned int nBytes = 0;
322
9.78k
  unsigned int *nBytesp = &nBytes;
323
324
9.78k
#ifdef HAVE_USELOCALE
325
9.78k
  locale_t oldlocale = uselocale(NULL);
326
9.78k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
9.78k
  tok->char_offset = 0;
332
9.78k
  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
9.78k
  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
9.78k
#ifdef HAVE_USELOCALE
347
9.78k
  {
348
9.78k
#ifdef HAVE_DUPLOCALE
349
9.78k
    locale_t duploc = duplocale(oldlocale);
350
9.78k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
9.78k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
9.78k
    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
9.78k
    uselocale(newloc);
375
9.78k
  }
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
1.06M
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
1.06M
  {
395
396
3.84M
  redo_char:
397
3.84M
    switch (state)
398
3.84M
    {
399
400
1.50M
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
1.65M
      while (is_ws_char(c))
403
151k
      {
404
151k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
151k
      }
407
1.50M
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
2.42k
      {
409
2.42k
        printbuf_reset(tok->pb);
410
2.42k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
2.42k
        state = json_tokener_state_comment_start;
412
2.42k
      }
413
1.50M
      else
414
1.50M
      {
415
1.50M
        state = saved_state;
416
1.50M
        goto redo_char;
417
1.50M
      }
418
2.42k
      break;
419
420
317k
    case json_tokener_state_start:
421
317k
      switch (c)
422
317k
      {
423
53.4k
      case '{':
424
53.4k
        state = json_tokener_state_eatws;
425
53.4k
        saved_state = json_tokener_state_object_field_start;
426
53.4k
        current = json_object_new_object();
427
53.4k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
53.4k
        break;
433
53.4k
      case '[':
434
13.3k
        state = json_tokener_state_eatws;
435
13.3k
        saved_state = json_tokener_state_array;
436
13.3k
        current = json_object_new_array();
437
13.3k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
13.3k
        break;
443
13.3k
      case 'I':
444
492
      case 'i':
445
492
        state = json_tokener_state_inf;
446
492
        printbuf_reset(tok->pb);
447
492
        tok->st_pos = 0;
448
492
        goto redo_char;
449
1.03k
      case 'N':
450
14.2k
      case 'n':
451
14.2k
        state = json_tokener_state_null; // or NaN
452
14.2k
        printbuf_reset(tok->pb);
453
14.2k
        tok->st_pos = 0;
454
14.2k
        goto redo_char;
455
504
      case '\'':
456
504
        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.5k
      case '"':
464
68.5k
        state = json_tokener_state_string;
465
68.5k
        printbuf_reset(tok->pb);
466
68.5k
        tok->quote_char = c;
467
68.5k
        break;
468
614
      case 'T':
469
1.26k
      case 't':
470
1.40k
      case 'F':
471
1.84k
      case 'f':
472
1.84k
        state = json_tokener_state_boolean;
473
1.84k
        printbuf_reset(tok->pb);
474
1.84k
        tok->st_pos = 0;
475
1.84k
        goto redo_char;
476
21.6k
      case '0':
477
29.2k
      case '1':
478
33.2k
      case '2':
479
34.6k
      case '3':
480
36.9k
      case '4':
481
158k
      case '5':
482
159k
      case '6':
483
160k
      case '7':
484
161k
      case '8':
485
162k
      case '9':
486
165k
      case '-':
487
165k
        state = json_tokener_state_number;
488
165k
        printbuf_reset(tok->pb);
489
165k
        tok->is_double = 0;
490
165k
        goto redo_char;
491
138
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
317k
      }
493
135k
      break;
494
495
311k
    case json_tokener_state_finish:
496
311k
      if (tok->depth == 0)
497
7.43k
        goto out;
498
304k
      obj = json_object_get(current);
499
304k
      json_tokener_reset_level(tok, tok->depth);
500
304k
      tok->depth--;
501
304k
      goto redo_char;
502
503
919
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
919
    {
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
919
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
7.69k
      while (tok->st_pos < (int)json_inf_str_len)
516
6.86k
      {
517
6.86k
        char inf_char = *str;
518
6.86k
        if (inf_char != json_inf_str[tok->st_pos] &&
519
3.04k
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
3.04k
              inf_char != json_inf_str_invert[tok->st_pos])
521
6.86k
           )
522
92
        {
523
92
          tok->err = json_tokener_error_parse_unexpected;
524
92
          goto out;
525
92
        }
526
6.77k
        tok->st_pos++;
527
6.77k
        (void)ADVANCE_CHAR(str, tok);
528
6.77k
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
6.77k
      }
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
827
      if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
539
401
      {
540
401
        is_negative = 1;
541
401
      }
542
827
      current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
543
827
      if (current == NULL)
544
0
      {
545
0
        tok->err = json_tokener_error_memory;
546
0
        goto out;
547
0
      }
548
827
      saved_state = json_tokener_state_finish;
549
827
      state = json_tokener_state_eatws;
550
827
      goto redo_char;
551
827
    }
552
0
    break;
553
70.6k
    case json_tokener_state_null: /* aka starts with 'n' */
554
70.6k
    {
555
70.6k
      int size;
556
70.6k
      int size_nan;
557
70.6k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
70.6k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
70.6k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
70.6k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
70.6k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
1.49k
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
69.1k
      {
564
69.1k
        if (tok->st_pos == json_null_str_len)
565
13.7k
        {
566
13.7k
          current = NULL;
567
13.7k
          saved_state = json_tokener_state_finish;
568
13.7k
          state = json_tokener_state_eatws;
569
13.7k
          goto redo_char;
570
13.7k
        }
571
69.1k
      }
572
1.49k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
1.49k
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
102
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
1.39k
      {
576
1.39k
        if (tok->st_pos == json_nan_str_len)
577
458
        {
578
458
          current = json_object_new_double(NAN);
579
458
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
458
          saved_state = json_tokener_state_finish;
585
458
          state = json_tokener_state_eatws;
586
458
          goto redo_char;
587
458
        }
588
1.39k
      }
589
102
      else
590
102
      {
591
102
        tok->err = json_tokener_error_parse_null;
592
102
        goto out;
593
102
      }
594
56.3k
      tok->st_pos++;
595
56.3k
    }
596
0
    break;
597
598
2.42k
    case json_tokener_state_comment_start:
599
2.42k
      if (c == '*')
600
734
      {
601
734
        state = json_tokener_state_comment;
602
734
      }
603
1.68k
      else if (c == '/')
604
1.62k
      {
605
1.62k
        state = json_tokener_state_comment_eol;
606
1.62k
      }
607
62
      else
608
62
      {
609
62
        tok->err = json_tokener_error_parse_comment;
610
62
        goto out;
611
62
      }
612
2.36k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
2.36k
      break;
614
615
3.59k
    case json_tokener_state_comment:
616
3.59k
    {
617
      /* Advance until we change state */
618
3.59k
      const char *case_start = str;
619
458k
      while (c != '*')
620
454k
      {
621
454k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
185
        {
623
185
          printbuf_memappend_checked(tok->pb, case_start,
624
185
                                     str - case_start);
625
185
          goto out;
626
185
        }
627
454k
      }
628
3.40k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
3.40k
      state = json_tokener_state_comment_end;
630
3.40k
    }
631
0
    break;
632
633
1.62k
    case json_tokener_state_comment_eol:
634
1.62k
    {
635
      /* Advance until we change state */
636
1.62k
      const char *case_start = str;
637
202k
      while (c != '\n')
638
201k
      {
639
201k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
115
        {
641
115
          printbuf_memappend_checked(tok->pb, case_start,
642
115
                                     str - case_start);
643
115
          goto out;
644
115
        }
645
201k
      }
646
1.51k
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
1.51k
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
1.51k
      state = json_tokener_state_eatws;
649
1.51k
    }
650
0
    break;
651
652
3.40k
    case json_tokener_state_comment_end:
653
3.40k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
3.40k
      if (c == '/')
655
542
      {
656
542
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
542
        state = json_tokener_state_eatws;
658
542
      }
659
2.86k
      else
660
2.86k
      {
661
2.86k
        state = json_tokener_state_comment;
662
2.86k
      }
663
3.40k
      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.74M
      while (1)
670
1.74M
      {
671
1.74M
        if (c == tok->quote_char)
672
68.2k
        {
673
68.2k
          printbuf_memappend_checked(tok->pb, case_start,
674
68.2k
                                     str - case_start);
675
68.2k
          current =
676
68.2k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
68.2k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
68.2k
          saved_state = json_tokener_state_finish;
683
68.2k
          state = json_tokener_state_eatws;
684
68.2k
          break;
685
68.2k
        }
686
1.67M
        else if (c == '\\')
687
32.4k
        {
688
32.4k
          printbuf_memappend_checked(tok->pb, case_start,
689
32.4k
                                     str - case_start);
690
32.4k
          saved_state = json_tokener_state_string;
691
32.4k
          state = json_tokener_state_string_escape;
692
32.4k
          break;
693
32.4k
        }
694
1.64M
        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.64M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
249
        {
702
249
          printbuf_memappend_checked(tok->pb, case_start,
703
249
                                     str - case_start);
704
249
          goto out;
705
249
        }
706
1.64M
      }
707
100k
    }
708
100k
    break;
709
710
100k
    case json_tokener_state_string_escape:
711
42.4k
      switch (c)
712
42.4k
      {
713
7.18k
      case '"':
714
23.0k
      case '\\':
715
23.4k
      case '/':
716
23.4k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
23.4k
        state = saved_state;
718
23.4k
        break;
719
936
      case 'b':
720
13.4k
      case 'n':
721
14.0k
      case 'r':
722
14.8k
      case 't':
723
15.2k
      case 'f':
724
15.2k
        if (c == 'b')
725
936
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
14.3k
        else if (c == 'n')
727
12.5k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.81k
        else if (c == 'r')
729
557
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
1.25k
        else if (c == 't')
731
861
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
393
        else if (c == 'f')
733
393
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
15.2k
        state = saved_state;
735
15.2k
        break;
736
3.71k
      case 'u':
737
3.71k
        tok->ucs_char = 0;
738
3.71k
        tok->st_pos = 0;
739
3.71k
        state = json_tokener_state_escape_unicode;
740
3.71k
        break;
741
39
      default: tok->err = json_tokener_error_parse_string; goto out;
742
42.4k
      }
743
42.4k
      break;
744
745
      // ===================================================
746
747
42.4k
    case json_tokener_state_escape_unicode:
748
4.87k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
19.3k
      while (1)
751
19.3k
      {
752
19.3k
        if (!c || !is_hex_char(c))
753
71
        {
754
71
          tok->err = json_tokener_error_parse_string;
755
71
          goto out;
756
71
        }
757
19.2k
        tok->ucs_char |=
758
19.2k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
19.2k
        tok->st_pos++;
760
19.2k
        if (tok->st_pos >= 4)
761
4.80k
          break;
762
763
14.4k
        (void)ADVANCE_CHAR(str, tok);
764
14.4k
        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
14.4k
      }
775
4.80k
      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
4.80k
      if (tok->high_surrogate)
781
1.14k
      {
782
1.14k
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
522
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
522
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
522
                                                tok->ucs_char);
787
522
        }
788
620
        else
789
620
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
620
          printbuf_memappend_checked(tok->pb,
794
620
                                     (char *)utf8_replacement_char, 3);
795
620
        }
796
1.14k
        tok->high_surrogate = 0;
797
1.14k
      }
798
799
4.80k
      if (tok->ucs_char < 0x80)
800
994
      {
801
994
        unsigned char unescaped_utf[1];
802
994
        unescaped_utf[0] = tok->ucs_char;
803
994
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
994
      }
805
3.80k
      else if (tok->ucs_char < 0x800)
806
335
      {
807
335
        unsigned char unescaped_utf[2];
808
335
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
335
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
335
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
335
      }
812
3.47k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
1.87k
      {
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
1.87k
        tok->high_surrogate = tok->ucs_char;
829
1.87k
        tok->ucs_char = 0;
830
1.87k
        state = json_tokener_state_escape_unicode_need_escape;
831
1.87k
        break;
832
1.87k
      }
833
1.59k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
520
      {
835
        /* Got a low surrogate not preceded by a high */
836
520
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
520
      }
838
1.07k
      else if (tok->ucs_char < 0x10000)
839
552
      {
840
552
        unsigned char unescaped_utf[3];
841
552
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
552
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
552
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
552
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
552
      }
846
522
      else if (tok->ucs_char < 0x110000)
847
522
      {
848
522
        unsigned char unescaped_utf[4];
849
522
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
522
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
522
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
522
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
522
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
522
      }
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.92k
      state = saved_state; // i.e. _state_string or _state_object_field
861
2.92k
    }
862
0
    break;
863
864
1.87k
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
1.87k
      if (!c || c != '\\')
868
428
      {
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
428
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
428
        tok->high_surrogate = 0;
875
428
        tok->ucs_char = 0;
876
428
        tok->st_pos = 0;
877
428
        state = saved_state;
878
428
        goto redo_char;
879
428
      }
880
1.44k
      state = json_tokener_state_escape_unicode_need_u;
881
1.44k
      break;
882
883
1.44k
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
1.44k
      if (!c || c != 'u')
886
296
      {
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
296
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
296
        tok->high_surrogate = 0;
894
296
        tok->ucs_char = 0;
895
296
        tok->st_pos = 0;
896
296
        state = json_tokener_state_string_escape;
897
296
        goto redo_char;
898
296
      }
899
1.15k
      state = json_tokener_state_escape_unicode;
900
1.15k
      break;
901
902
      // ===================================================
903
904
9.39k
    case json_tokener_state_boolean:
905
9.39k
    {
906
9.39k
      int size1, size2;
907
9.39k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
9.39k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
9.39k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
9.39k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
9.39k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
3.35k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
6.03k
      {
914
6.03k
        if (tok->st_pos == json_true_str_len)
915
1.18k
        {
916
1.18k
          current = json_object_new_boolean(1);
917
1.18k
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
1.18k
          saved_state = json_tokener_state_finish;
923
1.18k
          state = json_tokener_state_eatws;
924
1.18k
          goto redo_char;
925
1.18k
        }
926
6.03k
      }
927
3.35k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
3.35k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
149
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
3.20k
      {
931
3.20k
        if (tok->st_pos == json_false_str_len)
932
511
        {
933
511
          current = json_object_new_boolean(0);
934
511
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
511
          saved_state = json_tokener_state_finish;
940
511
          state = json_tokener_state_eatws;
941
511
          goto redo_char;
942
511
        }
943
3.20k
      }
944
149
      else
945
149
      {
946
149
        tok->err = json_tokener_error_parse_boolean;
947
149
        goto out;
948
149
      }
949
7.55k
      tok->st_pos++;
950
7.55k
    }
951
0
    break;
952
953
165k
    case json_tokener_state_number:
954
165k
    {
955
      /* Advance until we change state */
956
165k
      const char *case_start = str;
957
165k
      int case_len = 0;
958
165k
      int is_exponent = 0;
959
165k
      int neg_sign_ok = 1;
960
165k
      int pos_sign_ok = 0;
961
165k
      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
453k
      while (c && ((c >= '0' && c <= '9') ||
986
173k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
171k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
166k
                   (!tok->is_double && c == '.')))
989
287k
      {
990
287k
        pos_sign_ok = neg_sign_ok = 0;
991
287k
        ++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
287k
        switch (c)
1000
287k
        {
1001
895
        case '.':
1002
895
          tok->is_double = 1;
1003
895
          pos_sign_ok = 1;
1004
895
          neg_sign_ok = 1;
1005
895
          break;
1006
1.57k
        case 'e': /* FALLTHRU */
1007
2.53k
        case 'E':
1008
2.53k
          is_exponent = 1;
1009
2.53k
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
2.53k
          pos_sign_ok = neg_sign_ok = 1;
1012
2.53k
          break;
1013
284k
        default: break;
1014
287k
        }
1015
1016
287k
        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
287k
      }
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
165k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
2.93k
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
256
      {
1033
256
        tok->err = json_tokener_error_parse_number;
1034
256
        goto out;
1035
256
      }
1036
165k
      if (case_len > 0)
1037
165k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
165k
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1041
427
      {
1042
427
        state = json_tokener_state_inf;
1043
427
        tok->st_pos = 0;
1044
427
        goto redo_char;
1045
427
      }
1046
164k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
2.93k
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
6.43k
        while (printbuf_length(tok->pb) > 1)
1051
5.10k
        {
1052
5.10k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
5.10k
          if (last_char != 'e' && last_char != 'E' &&
1054
3.17k
              last_char != '-' && last_char != '+')
1055
1.60k
          {
1056
1.60k
            break;
1057
1.60k
          }
1058
3.50k
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
3.50k
          printbuf_length(tok->pb)--;
1060
3.50k
        }
1061
2.93k
      }
1062
164k
    }
1063
0
      {
1064
164k
        int64_t num64;
1065
164k
        uint64_t numuint64;
1066
164k
        double numd;
1067
164k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
2.26k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
2.24k
        {
1070
2.24k
          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
2.24k
          current = json_object_new_int64(num64);
1076
2.24k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
2.24k
        }
1082
162k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
159k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
159k
        {
1085
159k
          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
159k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
2.57k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
159k
          if (numuint64 <= INT64_MAX)
1097
159k
          {
1098
159k
            num64 = (uint64_t)numuint64;
1099
159k
            current = json_object_new_int64(num64);
1100
159k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
159k
          }
1106
650
          else
1107
650
          {
1108
650
            current = json_object_new_uint64(numuint64);
1109
650
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
650
          }
1115
159k
        }
1116
2.96k
        else if (tok->is_double &&
1117
2.93k
                 json_tokener_parse_double(
1118
2.93k
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
2.91k
        {
1120
2.91k
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
2.91k
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
2.91k
        }
1127
43
        else
1128
43
        {
1129
43
          tok->err = json_tokener_error_parse_number;
1130
43
          goto out;
1131
43
        }
1132
164k
        saved_state = json_tokener_state_finish;
1133
164k
        state = json_tokener_state_eatws;
1134
164k
        goto redo_char;
1135
164k
      }
1136
0
      break;
1137
1138
178k
    case json_tokener_state_array_after_sep:
1139
191k
    case json_tokener_state_array:
1140
191k
      if (c == ']')
1141
1.81k
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
1.81k
        json_object_array_shrink(current, 0);
1144
1145
1.81k
        if (state == json_tokener_state_array_after_sep &&
1146
615
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
1.81k
        saved_state = json_tokener_state_finish;
1152
1.81k
        state = json_tokener_state_eatws;
1153
1.81k
      }
1154
189k
      else
1155
189k
      {
1156
189k
        if (tok->depth >= tok->max_depth - 1)
1157
11
        {
1158
11
          tok->err = json_tokener_error_depth;
1159
11
          goto out;
1160
11
        }
1161
189k
        state = json_tokener_state_array_add;
1162
189k
        tok->depth++;
1163
189k
        json_tokener_reset_level(tok, tok->depth);
1164
189k
        goto redo_char;
1165
189k
      }
1166
1.81k
      break;
1167
1168
187k
    case json_tokener_state_array_add:
1169
187k
      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
187k
      saved_state = json_tokener_state_array_sep;
1175
187k
      state = json_tokener_state_eatws;
1176
187k
      goto redo_char;
1177
1178
187k
    case json_tokener_state_array_sep:
1179
187k
      if (c == ']')
1180
9.47k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
9.47k
        json_object_array_shrink(current, 0);
1183
1184
9.47k
        saved_state = json_tokener_state_finish;
1185
9.47k
        state = json_tokener_state_eatws;
1186
9.47k
      }
1187
178k
      else if (c == ',')
1188
178k
      {
1189
178k
        saved_state = json_tokener_state_array_after_sep;
1190
178k
        state = json_tokener_state_eatws;
1191
178k
      }
1192
136
      else
1193
136
      {
1194
136
        tok->err = json_tokener_error_parse_array;
1195
136
        goto out;
1196
136
      }
1197
187k
      break;
1198
1199
187k
    case json_tokener_state_object_field_start:
1200
138k
    case json_tokener_state_object_field_start_after_sep:
1201
138k
      if (c == '}')
1202
19.3k
      {
1203
19.3k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
198
            (tok->flags & JSON_TOKENER_STRICT))
1205
0
        {
1206
0
          tok->err = json_tokener_error_parse_unexpected;
1207
0
          goto out;
1208
0
        }
1209
19.3k
        saved_state = json_tokener_state_finish;
1210
19.3k
        state = json_tokener_state_eatws;
1211
19.3k
      }
1212
119k
      else if (c == '"' || c == '\'')
1213
119k
      {
1214
119k
        tok->quote_char = c;
1215
119k
        printbuf_reset(tok->pb);
1216
119k
        state = json_tokener_state_object_field;
1217
119k
      }
1218
72
      else
1219
72
      {
1220
72
        tok->err = json_tokener_error_parse_object_key_name;
1221
72
        goto out;
1222
72
      }
1223
138k
      break;
1224
1225
138k
    case json_tokener_state_object_field:
1226
128k
    {
1227
      /* Advance until we change state */
1228
128k
      const char *case_start = str;
1229
1.87M
      while (1)
1230
1.87M
      {
1231
1.87M
        if (c == tok->quote_char)
1232
118k
        {
1233
118k
          printbuf_memappend_checked(tok->pb, case_start,
1234
118k
                                     str - case_start);
1235
118k
          obj_field_name = strdup(tok->pb->buf);
1236
118k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
118k
          saved_state = json_tokener_state_object_field_end;
1242
118k
          state = json_tokener_state_eatws;
1243
118k
          break;
1244
118k
        }
1245
1.75M
        else if (c == '\\')
1246
9.68k
        {
1247
9.68k
          printbuf_memappend_checked(tok->pb, case_start,
1248
9.68k
                                     str - case_start);
1249
9.68k
          saved_state = json_tokener_state_object_field;
1250
9.68k
          state = json_tokener_state_string_escape;
1251
9.68k
          break;
1252
9.68k
        }
1253
1.74M
        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
1.74M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
175
        {
1261
175
          printbuf_memappend_checked(tok->pb, case_start,
1262
175
                                     str - case_start);
1263
175
          goto out;
1264
175
        }
1265
1.74M
      }
1266
128k
    }
1267
128k
    break;
1268
1269
128k
    case json_tokener_state_object_field_end:
1270
118k
      if (c == ':')
1271
118k
      {
1272
118k
        saved_state = json_tokener_state_object_value;
1273
118k
        state = json_tokener_state_eatws;
1274
118k
      }
1275
142
      else
1276
142
      {
1277
142
        tok->err = json_tokener_error_parse_object_key_sep;
1278
142
        goto out;
1279
142
      }
1280
118k
      break;
1281
1282
118k
    case json_tokener_state_object_value:
1283
118k
      if (tok->depth >= tok->max_depth - 1)
1284
3
      {
1285
3
        tok->err = json_tokener_error_depth;
1286
3
        goto out;
1287
3
      }
1288
118k
      state = json_tokener_state_object_value_add;
1289
118k
      tok->depth++;
1290
118k
      json_tokener_reset_level(tok, tok->depth);
1291
118k
      goto redo_char;
1292
1293
116k
    case json_tokener_state_object_value_add:
1294
116k
      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
116k
      free(obj_field_name);
1300
116k
      obj_field_name = NULL;
1301
116k
      saved_state = json_tokener_state_object_sep;
1302
116k
      state = json_tokener_state_eatws;
1303
116k
      goto redo_char;
1304
1305
116k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
116k
      if (c == '}')
1308
31.3k
      {
1309
31.3k
        saved_state = json_tokener_state_finish;
1310
31.3k
        state = json_tokener_state_eatws;
1311
31.3k
      }
1312
85.3k
      else if (c == ',')
1313
85.0k
      {
1314
85.0k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
85.0k
        state = json_tokener_state_eatws;
1316
85.0k
      }
1317
304
      else
1318
304
      {
1319
304
        tok->err = json_tokener_error_parse_object_value_sep;
1320
304
        goto out;
1321
304
      }
1322
116k
      break;
1323
3.84M
    }
1324
1.05M
    (void)ADVANCE_CHAR(str, tok);
1325
1.05M
    if (!c) // This is the char *before* advancing
1326
7
      break;
1327
1.05M
  } /* while(PEEK_CHAR) */
1328
1329
9.78k
out:
1330
9.78k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1331
0
  {
1332
0
    tok->err = json_tokener_error_parse_utf8_string;
1333
0
  }
1334
9.78k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
114
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
114
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
9.78k
  if (!c)
1342
8.16k
  {
1343
    /* We hit an eof char (0) */
1344
8.16k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
768
      tok->err = json_tokener_error_parse_eof;
1346
8.16k
  }
1347
1348
9.78k
#ifdef HAVE_USELOCALE
1349
9.78k
  uselocale(oldlocale);
1350
9.78k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
9.78k
  if (tok->err == json_tokener_success)
1357
7.51k
  {
1358
7.51k
    json_object *ret = json_object_get(current);
1359
7.51k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
15.3k
    for (ii = tok->depth; ii >= 0; ii--)
1363
7.86k
      json_tokener_reset_level(tok, ii);
1364
7.51k
    return ret;
1365
7.51k
  }
1366
1367
2.27k
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
2.27k
           tok->char_offset);
1369
2.27k
  return NULL;
1370
9.78k
}
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
2.93k
{
1411
2.93k
  char *end;
1412
2.93k
  *retval = strtod(buf, &end);
1413
2.93k
  if (buf + len == end)
1414
2.91k
    return 0; // It worked
1415
17
  return 1;
1416
2.93k
}