Coverage Report

Created: 2025-11-07 06:58

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
9.13k
#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
990k
{
71
990k
  return c == ' '
72
824k
      || c == '\t'
73
807k
      || c == '\n'
74
804k
      || c == '\r';
75
990k
}
76
77
static inline int is_hex_char(char c)
78
9.14k
{
79
9.14k
  return (c >= '0' && c <= '9')
80
3.11k
      || (c >= 'A' && c <= 'F')
81
294
      || (c >= 'a' && c <= 'f');
82
9.14k
}
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
417
{
134
417
  int jerr_int = (int)jerr;
135
417
  if (jerr_int < 0 ||
136
417
      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
417
  return json_tokener_errors[jerr];
140
417
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
834
{
144
834
  return tok->err;
145
834
}
146
147
/* Stuff for decoding unicode sequences */
148
1.34k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.05k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
244
#define DECODE_SURROGATE_PAIR(hi, lo) ((((hi)&0x3FF) << 10) + ((lo)&0x3FF) + 0x10000)
151
static unsigned char utf8_replacement_char[3] = {0xEF, 0xBF, 0xBD};
152
153
struct json_tokener *json_tokener_new_ex(int depth)
154
6.97k
{
155
6.97k
  struct json_tokener *tok;
156
157
6.97k
  if (depth < 1)
158
0
    return NULL;
159
160
6.97k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
6.97k
  if (!tok)
162
0
    return NULL;
163
6.97k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
6.97k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
6.97k
  tok->pb = printbuf_new();
170
6.97k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
6.97k
  tok->max_depth = depth;
177
6.97k
  json_tokener_reset(tok);
178
6.97k
  return tok;
179
6.97k
}
180
181
struct json_tokener *json_tokener_new(void)
182
6.97k
{
183
6.97k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
6.97k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
6.97k
{
188
6.97k
  if (!tok)
189
0
    return;
190
6.97k
  json_tokener_reset(tok);
191
6.97k
  if (tok->pb)
192
6.97k
    printbuf_free(tok->pb);
193
6.97k
  free(tok->stack);
194
6.97k
  free(tok);
195
6.97k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
297k
{
199
297k
  tok->stack[depth].state = json_tokener_state_eatws;
200
297k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
297k
  json_object_put(tok->stack[depth].current);
202
297k
  tok->stack[depth].current = NULL;
203
297k
  free(tok->stack[depth].obj_field_name);
204
297k
  tok->stack[depth].obj_field_name = NULL;
205
297k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
13.9k
{
209
13.9k
  int i;
210
13.9k
  if (!tok)
211
0
    return;
212
213
28.7k
  for (i = tok->depth; i >= 0; i--)
214
14.8k
    json_tokener_reset_level(tok, i);
215
13.9k
  tok->depth = 0;
216
13.9k
  tok->err = json_tokener_success;
217
13.9k
}
218
219
struct json_object *json_tokener_parse(const char *str)
220
0
{
221
0
  enum json_tokener_error jerr_ignored;
222
0
  struct json_object *obj;
223
0
  obj = json_tokener_parse_verbose(str, &jerr_ignored);
224
0
  return obj;
225
0
}
226
227
struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
228
0
{
229
0
  struct json_tokener *tok;
230
0
  struct json_object *obj;
231
232
0
  tok = json_tokener_new();
233
0
  if (!tok)
234
0
  {
235
0
    *error = json_tokener_error_memory;
236
0
    return NULL;
237
0
  }
238
0
  obj = json_tokener_parse_ex(tok, str, -1);
239
0
  *error = tok->err;
240
0
  if (tok->err != json_tokener_success
241
#if 0
242
    /* This would be a more sensible default, and cause parsing
243
     * things like "null123" to fail when the caller can't know
244
     * where the parsing left off, but starting to fail would
245
     * be a notable behaviour change.  Save for a 1.0 release.
246
     */
247
      || json_tokener_get_parse_end(tok) != strlen(str)
248
#endif
249
0
  )
250
251
0
  {
252
0
    if (obj != NULL)
253
0
      json_object_put(obj);
254
0
    obj = NULL;
255
0
  }
256
257
0
  json_tokener_free(tok);
258
0
  return obj;
259
0
}
260
261
3.96M
#define state tok->stack[tok->depth].state
262
1.55M
#define saved_state tok->stack[tok->depth].saved_state
263
581k
#define current tok->stack[tok->depth].current
264
542k
#define obj_field_name tok->stack[tok->depth].obj_field_name
265
266
/* Optimization:
267
 * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
268
 * iterating character-by character.  A large performance boost is
269
 * achieved by using tighter loops to locally handle units such as
270
 * comments and strings.  Loops that handle an entire token within
271
 * their scope also gather entire strings and pass them to
272
 * printbuf_memappend() in a single call, rather than calling
273
 * printbuf_memappend() one char at a time.
274
 *
275
 * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
276
 * common to both the main loop and the tighter loops.
277
 */
278
279
/* PEEK_CHAR(dest, tok) macro:
280
 *   Peeks at the current char and stores it in dest.
281
 *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
282
 *   Implicit inputs:  str, len, nBytesp vars
283
 */
284
#define PEEK_CHAR(dest, tok)                                                 \
285
3.48M
  (((tok)->char_offset == len)                                         \
286
3.48M
       ? (((tok)->depth == 0 && state == json_tokener_state_eatws &&   \
287
0
           saved_state == json_tokener_state_finish)                   \
288
0
              ? (((tok)->err = json_tokener_success), 0)               \
289
0
              : (((tok)->err = json_tokener_continue), 0))             \
290
3.48M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.48M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.48M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.48M
              : (((dest) = *str), 1)))
294
295
/* ADVANCE_CHAR() macro:
296
 *   Increments str & tok->char_offset.
297
 *   For convenience of existing conditionals, returns the old value of c (0 on eof).
298
 *   Implicit inputs:  c var
299
 */
300
5.97M
#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
294k
  do {                                                  \
308
294k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
294k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
294k
  } while (0)
314
315
/* End optimization macro defs */
316
317
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
318
6.97k
{
319
6.97k
  struct json_object *obj = NULL;
320
6.97k
  char c = '\1';
321
6.97k
  unsigned int nBytes = 0;
322
6.97k
  unsigned int *nBytesp = &nBytes;
323
324
6.97k
#ifdef HAVE_USELOCALE
325
6.97k
  locale_t oldlocale = uselocale(NULL);
326
6.97k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
6.97k
  tok->char_offset = 0;
332
6.97k
  tok->err = json_tokener_success;
333
334
  /* this interface is presently not 64-bit clean due to the int len argument
335
   * and the internal printbuf interface that takes 32-bit int len arguments
336
   * so the function limits the maximum string size to INT32_MAX (2GB).
337
   * If the function is called with len == -1 then strlen is called to check
338
   * the string length is less than INT32_MAX (2GB)
339
   */
340
6.97k
  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX))
341
0
  {
342
0
    tok->err = json_tokener_error_size;
343
0
    return NULL;
344
0
  }
345
346
6.97k
#ifdef HAVE_USELOCALE
347
6.97k
  {
348
6.97k
#ifdef HAVE_DUPLOCALE
349
6.97k
    locale_t duploc = duplocale(oldlocale);
350
6.97k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
6.97k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
6.97k
    if (newloc == NULL)
360
0
    {
361
0
      tok->err = json_tokener_error_memory;
362
0
#ifdef HAVE_DUPLOCALE
363
0
      freelocale(duploc);
364
0
#endif
365
0
      return NULL;
366
0
    }
367
#ifdef NEWLOCALE_NEEDS_FREELOCALE
368
#ifdef HAVE_DUPLOCALE
369
    // Older versions of FreeBSD (<12.4) don't free the locale
370
    // passed to newlocale(), so do it here
371
    freelocale(duploc);
372
#endif
373
#endif
374
6.97k
    uselocale(newloc);
375
6.97k
  }
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
802k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
802k
  {
395
396
2.04M
  redo_char:
397
2.04M
    switch (state)
398
2.04M
    {
399
400
804k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
989k
      while (is_ws_char(c))
403
185k
      {
404
185k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
185k
      }
407
804k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
821
      {
409
821
        printbuf_reset(tok->pb);
410
821
        printbuf_memappend_checked(tok->pb, &c, 1);
411
821
        state = json_tokener_state_comment_start;
412
821
      }
413
803k
      else
414
803k
      {
415
803k
        state = saved_state;
416
803k
        goto redo_char;
417
803k
      }
418
821
      break;
419
420
145k
    case json_tokener_state_start:
421
145k
      switch (c)
422
145k
      {
423
50.3k
      case '{':
424
50.3k
        state = json_tokener_state_eatws;
425
50.3k
        saved_state = json_tokener_state_object_field_start;
426
50.3k
        current = json_object_new_object();
427
50.3k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
50.3k
        break;
433
50.3k
      case '[':
434
9.77k
        state = json_tokener_state_eatws;
435
9.77k
        saved_state = json_tokener_state_array;
436
9.77k
        current = json_object_new_array();
437
9.77k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
9.77k
        break;
443
9.77k
      case 'I':
444
12
      case 'i':
445
12
        state = json_tokener_state_inf;
446
12
        printbuf_reset(tok->pb);
447
12
        tok->st_pos = 0;
448
12
        goto redo_char;
449
130
      case 'N':
450
315
      case 'n':
451
315
        state = json_tokener_state_null; // or NaN
452
315
        printbuf_reset(tok->pb);
453
315
        tok->st_pos = 0;
454
315
        goto redo_char;
455
74
      case '\'':
456
74
        if (tok->flags & JSON_TOKENER_STRICT)
457
0
        {
458
          /* in STRICT mode only double-quote are allowed */
459
0
          tok->err = json_tokener_error_parse_unexpected;
460
0
          goto out;
461
0
        }
462
        /* FALLTHRU */
463
74.0k
      case '"':
464
74.0k
        state = json_tokener_state_string;
465
74.0k
        printbuf_reset(tok->pb);
466
74.0k
        tok->quote_char = c;
467
74.0k
        break;
468
24
      case 'T':
469
59
      case 't':
470
186
      case 'F':
471
300
      case 'f':
472
300
        state = json_tokener_state_boolean;
473
300
        printbuf_reset(tok->pb);
474
300
        tok->st_pos = 0;
475
300
        goto redo_char;
476
2.44k
      case '0':
477
4.96k
      case '1':
478
5.75k
      case '2':
479
6.13k
      case '3':
480
7.46k
      case '4':
481
8.09k
      case '5':
482
8.23k
      case '6':
483
8.37k
      case '7':
484
8.43k
      case '8':
485
8.73k
      case '9':
486
10.6k
      case '-':
487
10.6k
        state = json_tokener_state_number;
488
10.6k
        printbuf_reset(tok->pb);
489
10.6k
        tok->is_double = 0;
490
10.6k
        goto redo_char;
491
85
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
145k
      }
493
134k
      break;
494
495
144k
    case json_tokener_state_finish:
496
144k
      if (tok->depth == 0)
497
6.53k
        goto out;
498
137k
      obj = json_object_get(current);
499
137k
      json_tokener_reset_level(tok, tok->depth);
500
137k
      tok->depth--;
501
137k
      goto redo_char;
502
503
14
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
14
    {
505
      /* If we were guaranteed to have len set, then we could (usually) handle
506
       * the entire "Infinity" check in a single strncmp (strncasecmp), but
507
       * since len might be -1 (i.e. "read until \0"), we need to check it
508
       * a character at a time.
509
       * Trying to handle it both ways would make this code considerably more
510
       * complicated with likely little performance benefit.
511
       */
512
14
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
39
      while (tok->st_pos < (int)json_inf_str_len)
516
39
      {
517
39
        char inf_char = *str;
518
39
        if (inf_char != json_inf_str[tok->st_pos] &&
519
28
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
28
              inf_char != json_inf_str_invert[tok->st_pos])
521
39
           )
522
14
        {
523
14
          tok->err = json_tokener_error_parse_unexpected;
524
14
          goto out;
525
14
        }
526
25
        tok->st_pos++;
527
25
        (void)ADVANCE_CHAR(str, tok);
528
25
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
25
      }
534
      /* We checked the full length of "Infinity", so create the object.
535
       * When handling -Infinity, the number parsing code will have dropped
536
       * the "-" into tok->pb for us, so check it now.
537
       */
538
0
      if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
539
0
      {
540
0
        is_negative = 1;
541
0
      }
542
0
      current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
543
0
      if (current == NULL)
544
0
      {
545
0
        tok->err = json_tokener_error_memory;
546
0
        goto out;
547
0
      }
548
0
      saved_state = json_tokener_state_finish;
549
0
      state = json_tokener_state_eatws;
550
0
      goto redo_char;
551
0
    }
552
0
    break;
553
1.39k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.39k
    {
555
1.39k
      int size;
556
1.39k
      int size_nan;
557
1.39k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.39k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.39k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.39k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.39k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
398
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
994
      {
564
994
        if (tok->st_pos == json_null_str_len)
565
168
        {
566
168
          current = NULL;
567
168
          saved_state = json_tokener_state_finish;
568
168
          state = json_tokener_state_eatws;
569
168
          goto redo_char;
570
168
        }
571
994
      }
572
398
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
398
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
22
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
376
      {
576
376
        if (tok->st_pos == json_nan_str_len)
577
125
        {
578
125
          current = json_object_new_double(NAN);
579
125
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
125
          saved_state = json_tokener_state_finish;
585
125
          state = json_tokener_state_eatws;
586
125
          goto redo_char;
587
125
        }
588
376
      }
589
22
      else
590
22
      {
591
22
        tok->err = json_tokener_error_parse_null;
592
22
        goto out;
593
22
      }
594
1.07k
      tok->st_pos++;
595
1.07k
    }
596
0
    break;
597
598
821
    case json_tokener_state_comment_start:
599
821
      if (c == '*')
600
144
      {
601
144
        state = json_tokener_state_comment;
602
144
      }
603
677
      else if (c == '/')
604
661
      {
605
661
        state = json_tokener_state_comment_eol;
606
661
      }
607
16
      else
608
16
      {
609
16
        tok->err = json_tokener_error_parse_comment;
610
16
        goto out;
611
16
      }
612
805
      printbuf_memappend_checked(tok->pb, &c, 1);
613
805
      break;
614
615
1.14k
    case json_tokener_state_comment:
616
1.14k
    {
617
      /* Advance until we change state */
618
1.14k
      const char *case_start = str;
619
23.3k
      while (c != '*')
620
22.2k
      {
621
22.2k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
21
        {
623
21
          printbuf_memappend_checked(tok->pb, case_start,
624
21
                                     str - case_start);
625
21
          goto out;
626
21
        }
627
22.2k
      }
628
1.12k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.12k
      state = json_tokener_state_comment_end;
630
1.12k
    }
631
0
    break;
632
633
661
    case json_tokener_state_comment_eol:
634
661
    {
635
      /* Advance until we change state */
636
661
      const char *case_start = str;
637
42.6k
      while (c != '\n')
638
42.0k
      {
639
42.0k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
46
        {
641
46
          printbuf_memappend_checked(tok->pb, case_start,
642
46
                                     str - case_start);
643
46
          goto out;
644
46
        }
645
42.0k
      }
646
615
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
615
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
615
      state = json_tokener_state_eatws;
649
615
    }
650
0
    break;
651
652
1.12k
    case json_tokener_state_comment_end:
653
1.12k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.12k
      if (c == '/')
655
119
      {
656
119
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
119
        state = json_tokener_state_eatws;
658
119
      }
659
1.00k
      else
660
1.00k
      {
661
1.00k
        state = json_tokener_state_comment;
662
1.00k
      }
663
1.12k
      break;
664
665
115k
    case json_tokener_state_string:
666
115k
    {
667
      /* Advance until we change state */
668
115k
      const char *case_start = str;
669
1.67M
      while (1)
670
1.67M
      {
671
1.67M
        if (c == tok->quote_char)
672
74.0k
        {
673
74.0k
          printbuf_memappend_checked(tok->pb, case_start,
674
74.0k
                                     str - case_start);
675
74.0k
          current =
676
74.0k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
74.0k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
74.0k
          saved_state = json_tokener_state_finish;
683
74.0k
          state = json_tokener_state_eatws;
684
74.0k
          break;
685
74.0k
        }
686
1.60M
        else if (c == '\\')
687
41.0k
        {
688
41.0k
          printbuf_memappend_checked(tok->pb, case_start,
689
41.0k
                                     str - case_start);
690
41.0k
          saved_state = json_tokener_state_string;
691
41.0k
          state = json_tokener_state_string_escape;
692
41.0k
          break;
693
41.0k
        }
694
1.56M
        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.56M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
41
        {
702
41
          printbuf_memappend_checked(tok->pb, case_start,
703
41
                                     str - case_start);
704
41
          goto out;
705
41
        }
706
1.56M
      }
707
115k
    }
708
115k
    break;
709
710
115k
    case json_tokener_state_string_escape:
711
46.5k
      switch (c)
712
46.5k
      {
713
8.53k
      case '"':
714
28.4k
      case '\\':
715
28.5k
      case '/':
716
28.5k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
28.5k
        state = saved_state;
718
28.5k
        break;
719
456
      case 'b':
720
15.0k
      case 'n':
721
15.2k
      case 'r':
722
15.8k
      case 't':
723
16.1k
      case 'f':
724
16.1k
        if (c == 'b')
725
456
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
15.6k
        else if (c == 'n')
727
14.5k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.10k
        else if (c == 'r')
729
270
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
838
        else if (c == 't')
731
570
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
268
        else if (c == 'f')
733
268
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
16.1k
        state = saved_state;
735
16.1k
        break;
736
1.91k
      case 'u':
737
1.91k
        tok->ucs_char = 0;
738
1.91k
        tok->st_pos = 0;
739
1.91k
        state = json_tokener_state_escape_unicode;
740
1.91k
        break;
741
12
      default: tok->err = json_tokener_error_parse_string; goto out;
742
46.5k
      }
743
46.5k
      break;
744
745
      // ===================================================
746
747
46.5k
    case json_tokener_state_escape_unicode:
748
2.29k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
9.14k
      while (1)
751
9.14k
      {
752
9.14k
        if (!c || !is_hex_char(c))
753
15
        {
754
15
          tok->err = json_tokener_error_parse_string;
755
15
          goto out;
756
15
        }
757
9.13k
        tok->ucs_char |=
758
9.13k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
9.13k
        tok->st_pos++;
760
9.13k
        if (tok->st_pos >= 4)
761
2.27k
          break;
762
763
6.85k
        (void)ADVANCE_CHAR(str, tok);
764
6.85k
        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
6.85k
      }
775
2.27k
      tok->st_pos = 0;
776
777
      /* Now, we have a full \uNNNN sequence in tok->ucs_char */
778
779
      /* If the *previous* sequence was a high surrogate ... */
780
2.27k
      if (tok->high_surrogate)
781
376
      {
782
376
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
244
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
244
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
244
                                                tok->ucs_char);
787
244
        }
788
132
        else
789
132
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
132
          printbuf_memappend_checked(tok->pb,
794
132
                                     (char *)utf8_replacement_char, 3);
795
132
        }
796
376
        tok->high_surrogate = 0;
797
376
      }
798
799
2.27k
      if (tok->ucs_char < 0x80)
800
869
      {
801
869
        unsigned char unescaped_utf[1];
802
869
        unescaped_utf[0] = tok->ucs_char;
803
869
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
869
      }
805
1.40k
      else if (tok->ucs_char < 0x800)
806
60
      {
807
60
        unsigned char unescaped_utf[2];
808
60
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
60
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
60
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
60
      }
812
1.34k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
668
      {
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
668
        tok->high_surrogate = tok->ucs_char;
829
668
        tok->ucs_char = 0;
830
668
        state = json_tokener_state_escape_unicode_need_escape;
831
668
        break;
832
668
      }
833
679
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
171
      {
835
        /* Got a low surrogate not preceded by a high */
836
171
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
171
      }
838
508
      else if (tok->ucs_char < 0x10000)
839
264
      {
840
264
        unsigned char unescaped_utf[3];
841
264
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
264
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
264
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
264
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
264
      }
846
244
      else if (tok->ucs_char < 0x110000)
847
244
      {
848
244
        unsigned char unescaped_utf[4];
849
244
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
244
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
244
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
244
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
244
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
244
      }
855
0
      else
856
0
      {
857
        /* Don't know what we got--insert the replacement char */
858
0
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
859
0
      }
860
1.60k
      state = saved_state; // i.e. _state_string or _state_object_field
861
1.60k
    }
862
0
    break;
863
864
668
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
668
      if (!c || c != '\\')
868
206
      {
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
206
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
206
        tok->high_surrogate = 0;
875
206
        tok->ucs_char = 0;
876
206
        tok->st_pos = 0;
877
206
        state = saved_state;
878
206
        goto redo_char;
879
206
      }
880
462
      state = json_tokener_state_escape_unicode_need_u;
881
462
      break;
882
883
462
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
462
      if (!c || c != 'u')
886
85
      {
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
85
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
85
        tok->high_surrogate = 0;
894
85
        tok->ucs_char = 0;
895
85
        tok->st_pos = 0;
896
85
        state = json_tokener_state_string_escape;
897
85
        goto redo_char;
898
85
      }
899
377
      state = json_tokener_state_escape_unicode;
900
377
      break;
901
902
      // ===================================================
903
904
1.66k
    case json_tokener_state_boolean:
905
1.66k
    {
906
1.66k
      int size1, size2;
907
1.66k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.66k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.66k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.66k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.66k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.41k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
244
      {
914
244
        if (tok->st_pos == json_true_str_len)
915
45
        {
916
45
          current = json_object_new_boolean(1);
917
45
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
45
          saved_state = json_tokener_state_finish;
923
45
          state = json_tokener_state_eatws;
924
45
          goto redo_char;
925
45
        }
926
244
      }
927
1.41k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.41k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
28
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.39k
      {
931
1.39k
        if (tok->st_pos == json_false_str_len)
932
227
        {
933
227
          current = json_object_new_boolean(0);
934
227
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
227
          saved_state = json_tokener_state_finish;
940
227
          state = json_tokener_state_eatws;
941
227
          goto redo_char;
942
227
        }
943
1.39k
      }
944
28
      else
945
28
      {
946
28
        tok->err = json_tokener_error_parse_boolean;
947
28
        goto out;
948
28
      }
949
1.36k
      tok->st_pos++;
950
1.36k
    }
951
0
    break;
952
953
10.6k
    case json_tokener_state_number:
954
10.6k
    {
955
      /* Advance until we change state */
956
10.6k
      const char *case_start = str;
957
10.6k
      int case_len = 0;
958
10.6k
      int is_exponent = 0;
959
10.6k
      int neg_sign_ok = 1;
960
10.6k
      int pos_sign_ok = 0;
961
10.6k
      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
72.9k
      while (c && ((c >= '0' && c <= '9') ||
986
13.9k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
13.4k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
11.0k
                   (!tok->is_double && c == '.')))
989
62.2k
      {
990
62.2k
        pos_sign_ok = neg_sign_ok = 0;
991
62.2k
        ++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
62.2k
        switch (c)
1000
62.2k
        {
1001
473
        case '.':
1002
473
          tok->is_double = 1;
1003
473
          pos_sign_ok = 1;
1004
473
          neg_sign_ok = 1;
1005
473
          break;
1006
467
        case 'e': /* FALLTHRU */
1007
495
        case 'E':
1008
495
          is_exponent = 1;
1009
495
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
495
          pos_sign_ok = neg_sign_ok = 1;
1012
495
          break;
1013
61.3k
        default: break;
1014
62.2k
        }
1015
1016
62.2k
        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
62.2k
      }
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
10.6k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
951
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
35
      {
1033
35
        tok->err = json_tokener_error_parse_number;
1034
35
        goto out;
1035
35
      }
1036
10.6k
      if (case_len > 0)
1037
10.6k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
10.6k
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1041
2
      {
1042
2
        state = json_tokener_state_inf;
1043
2
        tok->st_pos = 0;
1044
2
        goto redo_char;
1045
2
      }
1046
10.6k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
546
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
1.36k
        while (printbuf_length(tok->pb) > 1)
1051
1.33k
        {
1052
1.33k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
1.33k
          if (last_char != 'e' && last_char != 'E' &&
1054
903
              last_char != '-' && last_char != '+')
1055
517
          {
1056
517
            break;
1057
517
          }
1058
817
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
817
          printbuf_length(tok->pb)--;
1060
817
        }
1061
546
      }
1062
10.6k
    }
1063
0
      {
1064
10.6k
        int64_t num64;
1065
10.6k
        uint64_t numuint64;
1066
10.6k
        double numd;
1067
10.6k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
1.45k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
1.44k
        {
1070
1.44k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1071
0
          {
1072
0
            tok->err = json_tokener_error_parse_number;
1073
0
            goto out;
1074
0
          }
1075
1.44k
          current = json_object_new_int64(num64);
1076
1.44k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
1.44k
        }
1082
9.16k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
8.61k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
8.61k
        {
1085
8.61k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1086
0
          {
1087
0
            tok->err = json_tokener_error_parse_number;
1088
0
            goto out;
1089
0
          }
1090
8.61k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
1.62k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
8.61k
          if (numuint64 <= INT64_MAX)
1097
8.26k
          {
1098
8.26k
            num64 = (uint64_t)numuint64;
1099
8.26k
            current = json_object_new_int64(num64);
1100
8.26k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
8.26k
          }
1106
352
          else
1107
352
          {
1108
352
            current = json_object_new_uint64(numuint64);
1109
352
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
352
          }
1115
8.61k
        }
1116
550
        else if (tok->is_double &&
1117
546
                 json_tokener_parse_double(
1118
546
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
545
        {
1120
545
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
545
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
545
        }
1127
5
        else
1128
5
        {
1129
5
          tok->err = json_tokener_error_parse_number;
1130
5
          goto out;
1131
5
        }
1132
10.6k
        saved_state = json_tokener_state_finish;
1133
10.6k
        state = json_tokener_state_eatws;
1134
10.6k
        goto redo_char;
1135
10.6k
      }
1136
0
      break;
1137
1138
20.2k
    case json_tokener_state_array_after_sep:
1139
29.9k
    case json_tokener_state_array:
1140
29.9k
      if (c == ']')
1141
249
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
249
        json_object_array_shrink(current, 0);
1144
1145
249
        if (state == json_tokener_state_array_after_sep &&
1146
18
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
249
        saved_state = json_tokener_state_finish;
1152
249
        state = json_tokener_state_eatws;
1153
249
      }
1154
29.7k
      else
1155
29.7k
      {
1156
29.7k
        if (tok->depth >= tok->max_depth - 1)
1157
1
        {
1158
1
          tok->err = json_tokener_error_depth;
1159
1
          goto out;
1160
1
        }
1161
29.7k
        state = json_tokener_state_array_add;
1162
29.7k
        tok->depth++;
1163
29.7k
        json_tokener_reset_level(tok, tok->depth);
1164
29.7k
        goto redo_char;
1165
29.7k
      }
1166
249
      break;
1167
1168
29.4k
    case json_tokener_state_array_add:
1169
29.4k
      if (json_object_array_add(current, obj) != 0)
1170
0
      {
1171
0
        tok->err = json_tokener_error_memory;
1172
0
        goto out;
1173
0
      }
1174
29.4k
      saved_state = json_tokener_state_array_sep;
1175
29.4k
      state = json_tokener_state_eatws;
1176
29.4k
      goto redo_char;
1177
1178
29.4k
    case json_tokener_state_array_sep:
1179
29.4k
      if (c == ']')
1180
9.18k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
9.18k
        json_object_array_shrink(current, 0);
1183
1184
9.18k
        saved_state = json_tokener_state_finish;
1185
9.18k
        state = json_tokener_state_eatws;
1186
9.18k
      }
1187
20.2k
      else if (c == ',')
1188
20.2k
      {
1189
20.2k
        saved_state = json_tokener_state_array_after_sep;
1190
20.2k
        state = json_tokener_state_eatws;
1191
20.2k
      }
1192
26
      else
1193
26
      {
1194
26
        tok->err = json_tokener_error_parse_array;
1195
26
        goto out;
1196
26
      }
1197
29.4k
      break;
1198
1199
50.3k
    case json_tokener_state_object_field_start:
1200
128k
    case json_tokener_state_object_field_start_after_sep:
1201
128k
      if (c == '}')
1202
19.5k
      {
1203
19.5k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
3
            (tok->flags & JSON_TOKENER_STRICT))
1205
0
        {
1206
0
          tok->err = json_tokener_error_parse_unexpected;
1207
0
          goto out;
1208
0
        }
1209
19.5k
        saved_state = json_tokener_state_finish;
1210
19.5k
        state = json_tokener_state_eatws;
1211
19.5k
      }
1212
108k
      else if (c == '"' || c == '\'')
1213
108k
      {
1214
108k
        tok->quote_char = c;
1215
108k
        printbuf_reset(tok->pb);
1216
108k
        state = json_tokener_state_object_field;
1217
108k
      }
1218
17
      else
1219
17
      {
1220
17
        tok->err = json_tokener_error_parse_object_key_name;
1221
17
        goto out;
1222
17
      }
1223
128k
      break;
1224
1225
128k
    case json_tokener_state_object_field:
1226
114k
    {
1227
      /* Advance until we change state */
1228
114k
      const char *case_start = str;
1229
917k
      while (1)
1230
917k
      {
1231
917k
        if (c == tok->quote_char)
1232
108k
        {
1233
108k
          printbuf_memappend_checked(tok->pb, case_start,
1234
108k
                                     str - case_start);
1235
108k
          obj_field_name = strdup(tok->pb->buf);
1236
108k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
108k
          saved_state = json_tokener_state_object_field_end;
1242
108k
          state = json_tokener_state_eatws;
1243
108k
          break;
1244
108k
        }
1245
808k
        else if (c == '\\')
1246
5.47k
        {
1247
5.47k
          printbuf_memappend_checked(tok->pb, case_start,
1248
5.47k
                                     str - case_start);
1249
5.47k
          saved_state = json_tokener_state_object_field;
1250
5.47k
          state = json_tokener_state_string_escape;
1251
5.47k
          break;
1252
5.47k
        }
1253
803k
        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
803k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
21
        {
1261
21
          printbuf_memappend_checked(tok->pb, case_start,
1262
21
                                     str - case_start);
1263
21
          goto out;
1264
21
        }
1265
803k
      }
1266
114k
    }
1267
114k
    break;
1268
1269
114k
    case json_tokener_state_object_field_end:
1270
108k
      if (c == ':')
1271
108k
      {
1272
108k
        saved_state = json_tokener_state_object_value;
1273
108k
        state = json_tokener_state_eatws;
1274
108k
      }
1275
13
      else
1276
13
      {
1277
13
        tok->err = json_tokener_error_parse_object_key_sep;
1278
13
        goto out;
1279
13
      }
1280
108k
      break;
1281
1282
108k
    case json_tokener_state_object_value:
1283
108k
      if (tok->depth >= tok->max_depth - 1)
1284
0
      {
1285
0
        tok->err = json_tokener_error_depth;
1286
0
        goto out;
1287
0
      }
1288
108k
      state = json_tokener_state_object_value_add;
1289
108k
      tok->depth++;
1290
108k
      json_tokener_reset_level(tok, tok->depth);
1291
108k
      goto redo_char;
1292
1293
108k
    case json_tokener_state_object_value_add:
1294
108k
      if (json_object_object_add(current, obj_field_name, obj) != 0)
1295
0
      {
1296
0
        tok->err = json_tokener_error_memory;
1297
0
        goto out;
1298
0
      }
1299
108k
      free(obj_field_name);
1300
108k
      obj_field_name = NULL;
1301
108k
      saved_state = json_tokener_state_object_sep;
1302
108k
      state = json_tokener_state_eatws;
1303
108k
      goto redo_char;
1304
1305
108k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
108k
      if (c == '}')
1308
30.0k
      {
1309
30.0k
        saved_state = json_tokener_state_finish;
1310
30.0k
        state = json_tokener_state_eatws;
1311
30.0k
      }
1312
78.2k
      else if (c == ',')
1313
78.1k
      {
1314
78.1k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
78.1k
        state = json_tokener_state_eatws;
1316
78.1k
      }
1317
23
      else
1318
23
      {
1319
23
        tok->err = json_tokener_error_parse_object_value_sep;
1320
23
        goto out;
1321
23
      }
1322
108k
      break;
1323
2.04M
    }
1324
795k
    (void)ADVANCE_CHAR(str, tok);
1325
795k
    if (!c) // This is the char *before* advancing
1326
4
      break;
1327
795k
  } /* while(PEEK_CHAR) */
1328
1329
6.97k
out:
1330
6.97k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1331
0
  {
1332
0
    tok->err = json_tokener_error_parse_utf8_string;
1333
0
  }
1334
6.97k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
66
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
66
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
6.97k
  if (!c)
1342
6.68k
  {
1343
    /* We hit an eof char (0) */
1344
6.68k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
191
      tok->err = json_tokener_error_parse_eof;
1346
6.68k
  }
1347
1348
6.97k
#ifdef HAVE_USELOCALE
1349
6.97k
  uselocale(oldlocale);
1350
6.97k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
6.97k
  if (tok->err == json_tokener_success)
1357
6.56k
  {
1358
6.56k
    json_object *ret = json_object_get(current);
1359
6.56k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
13.1k
    for (ii = tok->depth; ii >= 0; ii--)
1363
6.60k
      json_tokener_reset_level(tok, ii);
1364
6.56k
    return ret;
1365
6.56k
  }
1366
1367
416
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
416
           tok->char_offset);
1369
416
  return NULL;
1370
6.97k
}
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
546
{
1411
546
  char *end;
1412
546
  *retval = strtod(buf, &end);
1413
546
  if (buf + len == end)
1414
545
    return 0; // It worked
1415
1
  return 1;
1416
546
}