Coverage Report

Created: 2025-06-13 06:36

/src/json-c/json_tokener.c
Line
Count
Source (jump to first uncovered line)
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
15.7k
#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.13M
{
71
1.13M
  return c == ' '
72
1.13M
      || c == '\t'
73
1.13M
      || c == '\n'
74
1.13M
      || c == '\r';
75
1.13M
}
76
77
static inline int is_hex_char(char c)
78
15.7k
{
79
15.7k
  return (c >= '0' && c <= '9')
80
15.7k
      || (c >= 'A' && c <= 'F')
81
15.7k
      || (c >= 'a' && c <= 'f');
82
15.7k
}
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
479
{
134
479
  int jerr_int = (int)jerr;
135
479
  if (jerr_int < 0 ||
136
479
      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
479
  return json_tokener_errors[jerr];
140
479
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
958
{
144
958
  return tok->err;
145
958
}
146
147
/* Stuff for decoding unicode sequences */
148
2.66k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFC00) == 0xD800)
149
1.92k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFC00) == 0xDC00)
150
386
#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
7.52k
{
155
7.52k
  struct json_tokener *tok;
156
157
7.52k
  if (depth < 1)
158
0
    return NULL;
159
160
7.52k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
7.52k
  if (!tok)
162
0
    return NULL;
163
7.52k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
7.52k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
7.52k
  tok->pb = printbuf_new();
170
7.52k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
7.52k
  tok->max_depth = depth;
177
7.52k
  json_tokener_reset(tok);
178
7.52k
  return tok;
179
7.52k
}
180
181
struct json_tokener *json_tokener_new(void)
182
7.52k
{
183
7.52k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
7.52k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
7.52k
{
188
7.52k
  if (!tok)
189
0
    return;
190
7.52k
  json_tokener_reset(tok);
191
7.52k
  if (tok->pb)
192
7.52k
    printbuf_free(tok->pb);
193
7.52k
  free(tok->stack);
194
7.52k
  free(tok);
195
7.52k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
347k
{
199
347k
  tok->stack[depth].state = json_tokener_state_eatws;
200
347k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
347k
  json_object_put(tok->stack[depth].current);
202
347k
  tok->stack[depth].current = NULL;
203
347k
  free(tok->stack[depth].obj_field_name);
204
347k
  tok->stack[depth].obj_field_name = NULL;
205
347k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
15.0k
{
209
15.0k
  int i;
210
15.0k
  if (!tok)
211
0
    return;
212
213
31.0k
  for (i = tok->depth; i >= 0; i--)
214
16.0k
    json_tokener_reset_level(tok, i);
215
15.0k
  tok->depth = 0;
216
15.0k
  tok->err = json_tokener_success;
217
15.0k
}
218
219
struct json_object *json_tokener_parse(const char *str)
220
0
{
221
0
  enum json_tokener_error jerr_ignored;
222
0
  struct json_object *obj;
223
0
  obj = json_tokener_parse_verbose(str, &jerr_ignored);
224
0
  return obj;
225
0
}
226
227
struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
228
0
{
229
0
  struct json_tokener *tok;
230
0
  struct json_object *obj;
231
232
0
  tok = json_tokener_new();
233
0
  if (!tok)
234
0
  {
235
0
    *error = json_tokener_error_memory;
236
0
    return NULL;
237
0
  }
238
0
  obj = json_tokener_parse_ex(tok, str, -1);
239
0
  *error = tok->err;
240
0
  if (tok->err != json_tokener_success
241
#if 0
242
    /* This would be a more sensible default, and cause parsing
243
     * things like "null123" to fail when the caller can't know
244
     * where the parsing left off, but starting to fail would
245
     * be a notable behaviour change.  Save for a 1.0 release.
246
     */
247
      || json_tokener_get_parse_end(tok) != strlen(str)
248
#endif
249
0
  )
250
251
0
  {
252
0
    if (obj != NULL)
253
0
      json_object_put(obj);
254
0
    obj = NULL;
255
0
  }
256
257
0
  json_tokener_free(tok);
258
0
  return obj;
259
0
}
260
261
4.67M
#define state tok->stack[tok->depth].state
262
1.83M
#define saved_state tok->stack[tok->depth].saved_state
263
681k
#define current tok->stack[tok->depth].current
264
616k
#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
4.48M
  (((tok)->char_offset == len)                                         \
286
4.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
4.48M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
4.48M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
4.48M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
4.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
7.79M
#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
375k
  do {                                                  \
308
375k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
375k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
375k
  } 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
7.52k
{
319
7.52k
  struct json_object *obj = NULL;
320
7.52k
  char c = '\1';
321
7.52k
  unsigned int nBytes = 0;
322
7.52k
  unsigned int *nBytesp = &nBytes;
323
324
7.52k
#ifdef HAVE_USELOCALE
325
7.52k
  locale_t oldlocale = uselocale(NULL);
326
7.52k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
7.52k
  tok->char_offset = 0;
332
7.52k
  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
7.52k
  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
7.52k
#ifdef HAVE_USELOCALE
347
7.52k
  {
348
7.52k
#ifdef HAVE_DUPLOCALE
349
7.52k
    locale_t duploc = duplocale(oldlocale);
350
7.52k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
7.52k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
7.52k
    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
7.52k
    uselocale(newloc);
375
7.52k
  }
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
958k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
958k
  {
395
396
2.40M
  redo_char:
397
2.40M
    switch (state)
398
2.40M
    {
399
400
933k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
1.13M
      while (is_ws_char(c))
403
201k
      {
404
201k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
201k
      }
407
933k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
1.33k
      {
409
1.33k
        printbuf_reset(tok->pb);
410
1.33k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
1.33k
        state = json_tokener_state_comment_start;
412
1.33k
      }
413
932k
      else
414
932k
      {
415
932k
        state = saved_state;
416
932k
        goto redo_char;
417
932k
      }
418
1.33k
      break;
419
420
170k
    case json_tokener_state_start:
421
170k
      switch (c)
422
170k
      {
423
54.5k
      case '{':
424
54.5k
        state = json_tokener_state_eatws;
425
54.5k
        saved_state = json_tokener_state_object_field_start;
426
54.5k
        current = json_object_new_object();
427
54.5k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
54.5k
        break;
433
54.5k
      case '[':
434
11.8k
        state = json_tokener_state_eatws;
435
11.8k
        saved_state = json_tokener_state_array;
436
11.8k
        current = json_object_new_array();
437
11.8k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
11.8k
        break;
443
11.8k
      case 'I':
444
16
      case 'i':
445
16
        state = json_tokener_state_inf;
446
16
        printbuf_reset(tok->pb);
447
16
        tok->st_pos = 0;
448
16
        goto redo_char;
449
153
      case 'N':
450
405
      case 'n':
451
405
        state = json_tokener_state_null; // or NaN
452
405
        printbuf_reset(tok->pb);
453
405
        tok->st_pos = 0;
454
405
        goto redo_char;
455
73
      case '\'':
456
73
        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
88.4k
      case '"':
464
88.4k
        state = json_tokener_state_string;
465
88.4k
        printbuf_reset(tok->pb);
466
88.4k
        tok->quote_char = c;
467
88.4k
        break;
468
24
      case 'T':
469
67
      case 't':
470
218
      case 'F':
471
358
      case 'f':
472
358
        state = json_tokener_state_boolean;
473
358
        printbuf_reset(tok->pb);
474
358
        tok->st_pos = 0;
475
358
        goto redo_char;
476
4.02k
      case '0':
477
6.95k
      case '1':
478
7.79k
      case '2':
479
8.15k
      case '3':
480
10.4k
      case '4':
481
11.2k
      case '5':
482
11.4k
      case '6':
483
11.6k
      case '7':
484
11.7k
      case '8':
485
12.1k
      case '9':
486
14.4k
      case '-':
487
14.4k
        state = json_tokener_state_number;
488
14.4k
        printbuf_reset(tok->pb);
489
14.4k
        tok->is_double = 0;
490
14.4k
        goto redo_char;
491
105
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
170k
      }
493
154k
      break;
494
495
168k
    case json_tokener_state_finish:
496
168k
      if (tok->depth == 0)
497
7.00k
        goto out;
498
161k
      obj = json_object_get(current);
499
161k
      json_tokener_reset_level(tok, tok->depth);
500
161k
      tok->depth--;
501
161k
      goto redo_char;
502
503
18
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
18
    {
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
18
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
47
      while (tok->st_pos < (int)json_inf_str_len)
516
47
      {
517
47
        char inf_char = *str;
518
47
        if (inf_char != json_inf_str[tok->st_pos] &&
519
47
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
35
              inf_char != json_inf_str_invert[tok->st_pos])
521
47
           )
522
18
        {
523
18
          tok->err = json_tokener_error_parse_unexpected;
524
18
          goto out;
525
18
        }
526
29
        tok->st_pos++;
527
29
        (void)ADVANCE_CHAR(str, tok);
528
29
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
29
      }
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.81k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.81k
    {
555
1.81k
      int size;
556
1.81k
      int size_nan;
557
1.81k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.81k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.81k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.81k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.81k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
1.81k
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
1.35k
      {
564
1.35k
        if (tok->st_pos == json_null_str_len)
565
236
        {
566
236
          current = NULL;
567
236
          saved_state = json_tokener_state_finish;
568
236
          state = json_tokener_state_eatws;
569
236
          goto redo_char;
570
236
        }
571
1.35k
      }
572
460
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
460
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
460
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
435
      {
576
435
        if (tok->st_pos == json_nan_str_len)
577
144
        {
578
144
          current = json_object_new_double(NAN);
579
144
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
144
          saved_state = json_tokener_state_finish;
585
144
          state = json_tokener_state_eatws;
586
144
          goto redo_char;
587
144
        }
588
435
      }
589
25
      else
590
25
      {
591
25
        tok->err = json_tokener_error_parse_null;
592
25
        goto out;
593
25
      }
594
1.41k
      tok->st_pos++;
595
1.41k
    }
596
0
    break;
597
598
1.33k
    case json_tokener_state_comment_start:
599
1.33k
      if (c == '*')
600
289
      {
601
289
        state = json_tokener_state_comment;
602
289
      }
603
1.04k
      else if (c == '/')
604
1.03k
      {
605
1.03k
        state = json_tokener_state_comment_eol;
606
1.03k
      }
607
16
      else
608
16
      {
609
16
        tok->err = json_tokener_error_parse_comment;
610
16
        goto out;
611
16
      }
612
1.31k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
1.31k
      break;
614
615
1.72k
    case json_tokener_state_comment:
616
1.72k
    {
617
      /* Advance until we change state */
618
1.72k
      const char *case_start = str;
619
22.4k
      while (c != '*')
620
20.7k
      {
621
20.7k
        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
20.7k
      }
628
1.70k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.70k
      state = json_tokener_state_comment_end;
630
1.70k
    }
631
0
    break;
632
633
1.03k
    case json_tokener_state_comment_eol:
634
1.03k
    {
635
      /* Advance until we change state */
636
1.03k
      const char *case_start = str;
637
59.5k
      while (c != '\n')
638
58.5k
      {
639
58.5k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
55
        {
641
55
          printbuf_memappend_checked(tok->pb, case_start,
642
55
                                     str - case_start);
643
55
          goto out;
644
55
        }
645
58.5k
      }
646
975
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
975
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
975
      state = json_tokener_state_eatws;
649
975
    }
650
0
    break;
651
652
1.70k
    case json_tokener_state_comment_end:
653
1.70k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.70k
      if (c == '/')
655
260
      {
656
260
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
260
        state = json_tokener_state_eatws;
658
260
      }
659
1.44k
      else
660
1.44k
      {
661
1.44k
        state = json_tokener_state_comment;
662
1.44k
      }
663
1.70k
      break;
664
665
150k
    case json_tokener_state_string:
666
150k
    {
667
      /* Advance until we change state */
668
150k
      const char *case_start = str;
669
2.32M
      while (1)
670
2.32M
      {
671
2.32M
        if (c == tok->quote_char)
672
88.4k
        {
673
88.4k
          printbuf_memappend_checked(tok->pb, case_start,
674
88.4k
                                     str - case_start);
675
88.4k
          current =
676
88.4k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
88.4k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
88.4k
          saved_state = json_tokener_state_finish;
683
88.4k
          state = json_tokener_state_eatws;
684
88.4k
          break;
685
88.4k
        }
686
2.24M
        else if (c == '\\')
687
62.3k
        {
688
62.3k
          printbuf_memappend_checked(tok->pb, case_start,
689
62.3k
                                     str - case_start);
690
62.3k
          saved_state = json_tokener_state_string;
691
62.3k
          state = json_tokener_state_string_escape;
692
62.3k
          break;
693
62.3k
        }
694
2.17M
        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
2.17M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
44
        {
702
44
          printbuf_memappend_checked(tok->pb, case_start,
703
44
                                     str - case_start);
704
44
          goto out;
705
44
        }
706
2.17M
      }
707
150k
    }
708
150k
    break;
709
710
150k
    case json_tokener_state_string_escape:
711
69.1k
      switch (c)
712
69.1k
      {
713
12.6k
      case '"':
714
42.5k
      case '\\':
715
42.6k
      case '/':
716
42.6k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
42.6k
        state = saved_state;
718
42.6k
        break;
719
561
      case 'b':
720
21.9k
      case 'n':
721
22.2k
      case 'r':
722
23.0k
      case 't':
723
23.3k
      case 'f':
724
23.3k
        if (c == 'b')
725
561
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
22.7k
        else if (c == 'n')
727
21.3k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.41k
        else if (c == 'r')
729
327
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
1.08k
        else if (c == 't')
731
777
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
308
        else if (c == 'f')
733
308
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
23.3k
        state = saved_state;
735
23.3k
        break;
736
3.10k
      case 'u':
737
3.10k
        tok->ucs_char = 0;
738
3.10k
        tok->st_pos = 0;
739
3.10k
        state = json_tokener_state_escape_unicode;
740
3.10k
        break;
741
15
      default: tok->err = json_tokener_error_parse_string; goto out;
742
69.1k
      }
743
69.1k
      break;
744
745
      // ===================================================
746
747
69.1k
    case json_tokener_state_escape_unicode:
748
3.95k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
15.7k
      while (1)
751
15.7k
      {
752
15.7k
        if (!c || !is_hex_char(c))
753
17
        {
754
17
          tok->err = json_tokener_error_parse_string;
755
17
          goto out;
756
17
        }
757
15.7k
        tok->ucs_char |=
758
15.7k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
15.7k
        tok->st_pos++;
760
15.7k
        if (tok->st_pos >= 4)
761
3.93k
          break;
762
763
11.8k
        (void)ADVANCE_CHAR(str, tok);
764
11.8k
        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
11.8k
      }
775
3.93k
      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
3.93k
      if (tok->high_surrogate)
781
847
      {
782
847
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
386
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
386
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
386
                                                tok->ucs_char);
787
386
        }
788
461
        else
789
461
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
461
          printbuf_memappend_checked(tok->pb,
794
461
                                     (char *)utf8_replacement_char, 3);
795
461
        }
796
847
        tok->high_surrogate = 0;
797
847
      }
798
799
3.93k
      if (tok->ucs_char < 0x80)
800
1.19k
      {
801
1.19k
        unsigned char unescaped_utf[1];
802
1.19k
        unescaped_utf[0] = tok->ucs_char;
803
1.19k
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
1.19k
      }
805
2.73k
      else if (tok->ucs_char < 0x800)
806
77
      {
807
77
        unsigned char unescaped_utf[2];
808
77
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
77
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
77
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
77
      }
812
2.66k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
1.58k
      {
814
        /*
815
         * The next two characters should be \u, HOWEVER,
816
         * we can't simply peek ahead here, because the
817
         * characters we need might not be passed to us
818
         * until a subsequent call to json_tokener_parse.
819
         * Instead, transition through a couple of states.
820
         * (now):
821
         *   _escape_unicode => _unicode_need_escape
822
         * (see a '\\' char):
823
         *   _unicode_need_escape => _unicode_need_u
824
         * (see a 'u' char):
825
         *   _unicode_need_u => _escape_unicode
826
         *      ...and we'll end up back around here.
827
         */
828
1.58k
        tok->high_surrogate = tok->ucs_char;
829
1.58k
        tok->ucs_char = 0;
830
1.58k
        state = json_tokener_state_escape_unicode_need_escape;
831
1.58k
        break;
832
1.58k
      }
833
1.08k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
266
      {
835
        /* Got a low surrogate not preceded by a high */
836
266
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
266
      }
838
814
      else if (tok->ucs_char < 0x10000)
839
428
      {
840
428
        unsigned char unescaped_utf[3];
841
428
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
428
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
428
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
428
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
428
      }
846
386
      else if (tok->ucs_char < 0x110000)
847
386
      {
848
386
        unsigned char unescaped_utf[4];
849
386
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
386
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
386
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
386
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
386
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
386
      }
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.35k
      state = saved_state; // i.e. _state_string or _state_object_field
861
2.35k
    }
862
0
    break;
863
864
1.58k
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
1.58k
      if (!c || c != '\\')
868
347
      {
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
347
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
347
        tok->high_surrogate = 0;
875
347
        tok->ucs_char = 0;
876
347
        tok->st_pos = 0;
877
347
        state = saved_state;
878
347
        goto redo_char;
879
347
      }
880
1.23k
      state = json_tokener_state_escape_unicode_need_u;
881
1.23k
      break;
882
883
1.23k
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
1.23k
      if (!c || c != 'u')
886
388
      {
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
388
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
388
        tok->high_surrogate = 0;
894
388
        tok->ucs_char = 0;
895
388
        tok->st_pos = 0;
896
388
        state = json_tokener_state_string_escape;
897
388
        goto redo_char;
898
388
      }
899
847
      state = json_tokener_state_escape_unicode;
900
847
      break;
901
902
      // ===================================================
903
904
1.99k
    case json_tokener_state_boolean:
905
1.99k
    {
906
1.99k
      int size1, size2;
907
1.99k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.99k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.99k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.99k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.99k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.99k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
276
      {
914
276
        if (tok->st_pos == json_true_str_len)
915
51
        {
916
51
          current = json_object_new_boolean(1);
917
51
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
51
          saved_state = json_tokener_state_finish;
923
51
          state = json_tokener_state_eatws;
924
51
          goto redo_char;
925
51
        }
926
276
      }
927
1.72k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.72k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
1.72k
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.69k
      {
931
1.69k
        if (tok->st_pos == json_false_str_len)
932
277
        {
933
277
          current = json_object_new_boolean(0);
934
277
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
277
          saved_state = json_tokener_state_finish;
940
277
          state = json_tokener_state_eatws;
941
277
          goto redo_char;
942
277
        }
943
1.69k
      }
944
30
      else
945
30
      {
946
30
        tok->err = json_tokener_error_parse_boolean;
947
30
        goto out;
948
30
      }
949
1.63k
      tok->st_pos++;
950
1.63k
    }
951
0
    break;
952
953
14.4k
    case json_tokener_state_number:
954
14.4k
    {
955
      /* Advance until we change state */
956
14.4k
      const char *case_start = str;
957
14.4k
      int case_len = 0;
958
14.4k
      int is_exponent = 0;
959
14.4k
      int neg_sign_ok = 1;
960
14.4k
      int pos_sign_ok = 0;
961
14.4k
      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
106k
      while (c && ((c >= '0' && c <= '9') ||
986
106k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
106k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
106k
                   (!tok->is_double && c == '.')))
989
92.1k
      {
990
92.1k
        pos_sign_ok = neg_sign_ok = 0;
991
92.1k
        ++case_len;
992
993
        /* non-digit characters checks */
994
        /* note: since the main loop condition to get here was
995
         * an input starting with 0-9 or '-', we are
996
         * protected from input starting with '.' or
997
         * e/E.
998
         */
999
92.1k
        switch (c)
1000
92.1k
        {
1001
416
        case '.':
1002
416
          tok->is_double = 1;
1003
416
          pos_sign_ok = 1;
1004
416
          neg_sign_ok = 1;
1005
416
          break;
1006
400
        case 'e': /* FALLTHRU */
1007
434
        case 'E':
1008
434
          is_exponent = 1;
1009
434
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
434
          pos_sign_ok = neg_sign_ok = 1;
1012
434
          break;
1013
91.3k
        default: break;
1014
92.1k
        }
1015
1016
92.1k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1017
0
        {
1018
0
          printbuf_memappend_checked(tok->pb, case_start, case_len);
1019
0
          goto out;
1020
0
        }
1021
92.1k
      }
1022
      /*
1023
        Now we know c isn't a valid number char, but check whether
1024
        it might have been intended to be, and return a potentially
1025
        more understandable error right away.
1026
        However, if we're at the top-level, use the number as-is
1027
        because c can be part of a new object to parse on the
1028
        next call to json_tokener_parse().
1029
       */
1030
14.4k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
14.4k
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
41
      {
1033
41
        tok->err = json_tokener_error_parse_number;
1034
41
        goto out;
1035
41
      }
1036
14.4k
      if (case_len > 0)
1037
14.4k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
14.4k
      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
14.4k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
495
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
1.13k
        while (printbuf_length(tok->pb) > 1)
1051
1.10k
        {
1052
1.10k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
1.10k
          if (last_char != 'e' && last_char != 'E' &&
1054
1.10k
              last_char != '-' && last_char != '+')
1055
469
          {
1056
469
            break;
1057
469
          }
1058
639
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
639
          printbuf_length(tok->pb)--;
1060
639
        }
1061
495
      }
1062
14.4k
    }
1063
0
      {
1064
14.4k
        int64_t num64;
1065
14.4k
        uint64_t numuint64;
1066
14.4k
        double numd;
1067
14.4k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
14.4k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
1.89k
        {
1070
1.89k
          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.89k
          current = json_object_new_int64(num64);
1076
1.89k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
1.89k
        }
1082
12.5k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
12.5k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
12.0k
        {
1085
12.0k
          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
12.0k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
12.0k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
12.0k
          if (numuint64 <= INT64_MAX)
1097
11.5k
          {
1098
11.5k
            num64 = (uint64_t)numuint64;
1099
11.5k
            current = json_object_new_int64(num64);
1100
11.5k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
11.5k
          }
1106
536
          else
1107
536
          {
1108
536
            current = json_object_new_uint64(numuint64);
1109
536
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
536
          }
1115
12.0k
        }
1116
500
        else if (tok->is_double &&
1117
500
                 json_tokener_parse_double(
1118
495
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
493
        {
1120
493
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
493
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
493
        }
1127
7
        else
1128
7
        {
1129
7
          tok->err = json_tokener_error_parse_number;
1130
7
          goto out;
1131
7
        }
1132
14.4k
        saved_state = json_tokener_state_finish;
1133
14.4k
        state = json_tokener_state_eatws;
1134
14.4k
        goto redo_char;
1135
14.4k
      }
1136
0
      break;
1137
1138
27.5k
    case json_tokener_state_array_after_sep:
1139
39.3k
    case json_tokener_state_array:
1140
39.3k
      if (c == ']')
1141
317
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
317
        json_object_array_shrink(current, 0);
1144
1145
317
        if (state == json_tokener_state_array_after_sep &&
1146
317
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
317
        saved_state = json_tokener_state_finish;
1152
317
        state = json_tokener_state_eatws;
1153
317
      }
1154
39.0k
      else
1155
39.0k
      {
1156
39.0k
        if (tok->depth >= tok->max_depth - 1)
1157
1
        {
1158
1
          tok->err = json_tokener_error_depth;
1159
1
          goto out;
1160
1
        }
1161
39.0k
        state = json_tokener_state_array_add;
1162
39.0k
        tok->depth++;
1163
39.0k
        json_tokener_reset_level(tok, tok->depth);
1164
39.0k
        goto redo_char;
1165
39.0k
      }
1166
317
      break;
1167
1168
38.7k
    case json_tokener_state_array_add:
1169
38.7k
      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
38.7k
      saved_state = json_tokener_state_array_sep;
1175
38.7k
      state = json_tokener_state_eatws;
1176
38.7k
      goto redo_char;
1177
1178
38.7k
    case json_tokener_state_array_sep:
1179
38.7k
      if (c == ']')
1180
11.1k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
11.1k
        json_object_array_shrink(current, 0);
1183
1184
11.1k
        saved_state = json_tokener_state_finish;
1185
11.1k
        state = json_tokener_state_eatws;
1186
11.1k
      }
1187
27.5k
      else if (c == ',')
1188
27.5k
      {
1189
27.5k
        saved_state = json_tokener_state_array_after_sep;
1190
27.5k
        state = json_tokener_state_eatws;
1191
27.5k
      }
1192
27
      else
1193
27
      {
1194
27
        tok->err = json_tokener_error_parse_array;
1195
27
        goto out;
1196
27
      }
1197
38.6k
      break;
1198
1199
54.5k
    case json_tokener_state_object_field_start:
1200
144k
    case json_tokener_state_object_field_start_after_sep:
1201
144k
      if (c == '}')
1202
21.0k
      {
1203
21.0k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
21.0k
            (tok->flags & JSON_TOKENER_STRICT))
1205
0
        {
1206
0
          tok->err = json_tokener_error_parse_unexpected;
1207
0
          goto out;
1208
0
        }
1209
21.0k
        saved_state = json_tokener_state_finish;
1210
21.0k
        state = json_tokener_state_eatws;
1211
21.0k
      }
1212
123k
      else if (c == '"' || c == '\'')
1213
123k
      {
1214
123k
        tok->quote_char = c;
1215
123k
        printbuf_reset(tok->pb);
1216
123k
        state = json_tokener_state_object_field;
1217
123k
      }
1218
21
      else
1219
21
      {
1220
21
        tok->err = json_tokener_error_parse_object_key_name;
1221
21
        goto out;
1222
21
      }
1223
144k
      break;
1224
1225
144k
    case json_tokener_state_object_field:
1226
130k
    {
1227
      /* Advance until we change state */
1228
130k
      const char *case_start = str;
1229
1.09M
      while (1)
1230
1.09M
      {
1231
1.09M
        if (c == tok->quote_char)
1232
123k
        {
1233
123k
          printbuf_memappend_checked(tok->pb, case_start,
1234
123k
                                     str - case_start);
1235
123k
          obj_field_name = strdup(tok->pb->buf);
1236
123k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
123k
          saved_state = json_tokener_state_object_field_end;
1242
123k
          state = json_tokener_state_eatws;
1243
123k
          break;
1244
123k
        }
1245
973k
        else if (c == '\\')
1246
6.35k
        {
1247
6.35k
          printbuf_memappend_checked(tok->pb, case_start,
1248
6.35k
                                     str - case_start);
1249
6.35k
          saved_state = json_tokener_state_object_field;
1250
6.35k
          state = json_tokener_state_string_escape;
1251
6.35k
          break;
1252
6.35k
        }
1253
966k
        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
966k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
23
        {
1261
23
          printbuf_memappend_checked(tok->pb, case_start,
1262
23
                                     str - case_start);
1263
23
          goto out;
1264
23
        }
1265
966k
      }
1266
130k
    }
1267
130k
    break;
1268
1269
130k
    case json_tokener_state_object_field_end:
1270
123k
      if (c == ':')
1271
123k
      {
1272
123k
        saved_state = json_tokener_state_object_value;
1273
123k
        state = json_tokener_state_eatws;
1274
123k
      }
1275
26
      else
1276
26
      {
1277
26
        tok->err = json_tokener_error_parse_object_key_sep;
1278
26
        goto out;
1279
26
      }
1280
123k
      break;
1281
1282
123k
    case json_tokener_state_object_value:
1283
123k
      if (tok->depth >= tok->max_depth - 1)
1284
0
      {
1285
0
        tok->err = json_tokener_error_depth;
1286
0
        goto out;
1287
0
      }
1288
123k
      state = json_tokener_state_object_value_add;
1289
123k
      tok->depth++;
1290
123k
      json_tokener_reset_level(tok, tok->depth);
1291
123k
      goto redo_char;
1292
1293
123k
    case json_tokener_state_object_value_add:
1294
123k
      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
123k
      free(obj_field_name);
1300
123k
      obj_field_name = NULL;
1301
123k
      saved_state = json_tokener_state_object_sep;
1302
123k
      state = json_tokener_state_eatws;
1303
123k
      goto redo_char;
1304
1305
123k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
123k
      if (c == '}')
1308
32.7k
      {
1309
32.7k
        saved_state = json_tokener_state_finish;
1310
32.7k
        state = json_tokener_state_eatws;
1311
32.7k
      }
1312
90.2k
      else if (c == ',')
1313
90.2k
      {
1314
90.2k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
90.2k
        state = json_tokener_state_eatws;
1316
90.2k
      }
1317
19
      else
1318
19
      {
1319
19
        tok->err = json_tokener_error_parse_object_value_sep;
1320
19
        goto out;
1321
19
      }
1322
123k
      break;
1323
2.40M
    }
1324
951k
    (void)ADVANCE_CHAR(str, tok);
1325
951k
    if (!c) // This is the char *before* advancing
1326
8
      break;
1327
951k
  } /* while(PEEK_CHAR) */
1328
1329
7.52k
out:
1330
7.52k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1331
0
  {
1332
0
    tok->err = json_tokener_error_parse_utf8_string;
1333
0
  }
1334
7.52k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
7.52k
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
67
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
7.52k
  if (!c)
1342
7.18k
  {
1343
    /* We hit an eof char (0) */
1344
7.18k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
211
      tok->err = json_tokener_error_parse_eof;
1346
7.18k
  }
1347
1348
7.52k
#ifdef HAVE_USELOCALE
1349
7.52k
  uselocale(oldlocale);
1350
7.52k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
7.52k
  if (tok->err == json_tokener_success)
1357
7.04k
  {
1358
7.04k
    json_object *ret = json_object_get(current);
1359
7.04k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
14.1k
    for (ii = tok->depth; ii >= 0; ii--)
1363
7.08k
      json_tokener_reset_level(tok, ii);
1364
7.04k
    return ret;
1365
7.04k
  }
1366
1367
478
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
478
           tok->char_offset);
1369
478
  return NULL;
1370
7.52k
}
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
495
{
1411
495
  char *end;
1412
495
  *retval = strtod(buf, &end);
1413
495
  if (buf + len == end)
1414
493
    return 0; // It worked
1415
2
  return 1;
1416
495
}