Coverage Report

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