Coverage Report

Created: 2026-10-28 07:07

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
12.7k
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9)
48
49
#if !HAVE_STRNCASECMP && defined(_WIN32)
50
/* MSC has the version as _strnicmp */
51
#define strncasecmp _strnicmp
52
#elif !HAVE_STRNCASECMP
53
#error You do not have strncasecmp on your system.
54
#endif /* HAVE_STRNCASECMP */
55
56
#if defined(_MSC_VER) && (_MSC_VER <= 1800)
57
/* VS2013 doesn't know about "inline" */
58
#define inline __inline
59
#elif defined(AIX_CC)
60
#define inline
61
#endif
62
63
/* The following helper functions are used to speed up parsing. They
64
 * are faster than their ctype counterparts because they assume that
65
 * the input is in ASCII and that the locale is set to "C". The
66
 * compiler will also inline these functions, providing an additional
67
 * speedup by saving on function calls.
68
 */
69
static inline int is_ws_char(char c)
70
1.10M
{
71
1.10M
  return c == ' '
72
884k
      || c == '\t'
73
855k
      || c == '\n'
74
852k
      || c == '\r';
75
1.10M
}
76
77
static inline int is_hex_char(char c)
78
12.7k
{
79
12.7k
  return (c >= '0' && c <= '9')
80
4.17k
      || (c >= 'A' && c <= 'F')
81
243
      || (c >= 'a' && c <= 'f');
82
12.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
412
{
134
412
  int jerr_int = (int)jerr;
135
412
  if (jerr_int < 0 ||
136
412
      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
412
  return json_tokener_errors[jerr];
140
412
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
824
{
144
824
  return tok->err;
145
824
}
146
147
/* Stuff for decoding unicode sequences */
148
2.20k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.98k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
329
#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.17k
{
155
7.17k
  struct json_tokener *tok;
156
157
7.17k
  if (depth < 1)
158
0
    return NULL;
159
160
7.17k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
7.17k
  if (!tok)
162
0
    return NULL;
163
7.17k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
7.17k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
7.17k
  tok->pb = printbuf_new();
170
7.17k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
7.17k
  tok->max_depth = depth;
177
7.17k
  json_tokener_reset(tok);
178
7.17k
  return tok;
179
7.17k
}
180
181
struct json_tokener *json_tokener_new(void)
182
7.17k
{
183
7.17k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
7.17k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
7.17k
{
188
7.17k
  if (!tok)
189
0
    return;
190
7.17k
  json_tokener_reset(tok);
191
7.17k
  if (tok->pb)
192
7.17k
    printbuf_free(tok->pb);
193
7.17k
  free(tok->stack);
194
7.17k
  free(tok);
195
7.17k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
315k
{
199
315k
  tok->stack[depth].state = json_tokener_state_eatws;
200
315k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
315k
  json_object_put(tok->stack[depth].current);
202
315k
  tok->stack[depth].current = NULL;
203
315k
  free(tok->stack[depth].obj_field_name);
204
315k
  tok->stack[depth].obj_field_name = NULL;
205
315k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
14.3k
{
209
14.3k
  int i;
210
14.3k
  if (!tok)
211
0
    return;
212
213
29.7k
  for (i = tok->depth; i >= 0; i--)
214
15.3k
    json_tokener_reset_level(tok, i);
215
14.3k
  tok->depth = 0;
216
14.3k
  tok->err = json_tokener_success;
217
14.3k
  tok->high_surrogate = 0;
218
14.3k
}
219
220
struct json_object *json_tokener_parse(const char *str)
221
0
{
222
0
  enum json_tokener_error jerr_ignored;
223
0
  struct json_object *obj;
224
0
  obj = json_tokener_parse_verbose(str, &jerr_ignored);
225
0
  return obj;
226
0
}
227
228
struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
229
0
{
230
0
  struct json_tokener *tok;
231
0
  struct json_object *obj;
232
233
0
  tok = json_tokener_new();
234
0
  if (!tok)
235
0
  {
236
0
    *error = json_tokener_error_memory;
237
0
    return NULL;
238
0
  }
239
0
  obj = json_tokener_parse_ex(tok, str, -1);
240
0
  *error = tok->err;
241
0
  if (tok->err != json_tokener_success
242
#if 0
243
    /* This would be a more sensible default, and cause parsing
244
     * things like "null123" to fail when the caller can't know
245
     * where the parsing left off, but starting to fail would
246
     * be a notable behaviour change.  Save for a 1.0 release.
247
     */
248
      || json_tokener_get_parse_end(tok) != strlen(str)
249
#endif
250
0
  )
251
252
0
  {
253
0
    if (obj != NULL)
254
0
      json_object_put(obj);
255
0
    obj = NULL;
256
0
  }
257
258
0
  json_tokener_free(tok);
259
0
  return obj;
260
0
}
261
262
4.23M
#define state tok->stack[tok->depth].state
263
1.66M
#define saved_state tok->stack[tok->depth].saved_state
264
616k
#define current tok->stack[tok->depth].current
265
575k
#define obj_field_name tok->stack[tok->depth].obj_field_name
266
267
/* Optimization:
268
 * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
269
 * iterating character-by character.  A large performance boost is
270
 * achieved by using tighter loops to locally handle units such as
271
 * comments and strings.  Loops that handle an entire token within
272
 * their scope also gather entire strings and pass them to
273
 * printbuf_memappend() in a single call, rather than calling
274
 * printbuf_memappend() one char at a time.
275
 *
276
 * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
277
 * common to both the main loop and the tighter loops.
278
 */
279
280
/* PEEK_CHAR(dest, tok) macro:
281
 *   Peeks at the current char and stores it in dest.
282
 *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
283
 *   Implicit inputs:  str, len, nBytesp vars
284
 */
285
#define PEEK_CHAR(dest, tok)                                                 \
286
3.90M
  (((tok)->char_offset == len)                                         \
287
3.90M
       ? (((tok)->depth == 0 && state == json_tokener_state_eatws &&   \
288
0
           saved_state == json_tokener_state_finish)                   \
289
0
              ? (((tok)->err = json_tokener_success), 0)               \
290
0
              : (((tok)->err = json_tokener_continue), 0))             \
291
3.90M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
292
3.90M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
293
3.90M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
294
3.90M
              : (((dest) = *str), 1)))
295
296
/* ADVANCE_CHAR() macro:
297
 *   Increments str & tok->char_offset.
298
 *   For convenience of existing conditionals, returns the old value of c (0 on eof).
299
 *   Implicit inputs:  c var
300
 */
301
6.66M
#define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c)
302
303
/* printbuf_memappend_checked(p, s, l) macro:
304
 *   Add string s of length l to printbuffer p.
305
 *   If operation fails abort parse operation with memory error.
306
 */
307
#define printbuf_memappend_checked(p, s, l)                   \
308
327k
  do {                                                  \
309
327k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
310
327k
    {                                             \
311
0
      tok->err = json_tokener_error_memory; \
312
0
      goto out;                             \
313
0
    }                                             \
314
327k
  } while (0)
315
316
/* End optimization macro defs */
317
318
#ifdef HAVE_USELOCALE
319
/* One-time C-numeric locale, created on first call and reused forever.
320
 * Avoids per-call duplocale() overhead and the memory leak seen on AIX
321
 * where freelocale() does not release all locale category memory.
322
 * Freed on library unload by json_tokener_locale_fini().
323
 */
324
static locale_t c_numeric_locale = (locale_t)0;
325
#endif /* HAVE_USELOCALE */
326
327
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
328
7.17k
{
329
7.17k
  struct json_object *obj = NULL;
330
7.17k
  char c = '\1';
331
7.17k
  unsigned int nBytes = 0;
332
7.17k
  unsigned int *nBytesp = &nBytes;
333
334
7.17k
#ifdef HAVE_USELOCALE
335
7.17k
  locale_t oldlocale = uselocale(NULL);
336
#elif defined(HAVE_SETLOCALE)
337
  char *oldlocale = NULL;
338
#endif
339
340
7.17k
  tok->char_offset = 0;
341
7.17k
  tok->err = json_tokener_success;
342
343
  /* this interface is presently not 64-bit clean due to the int len argument
344
   * and the internal printbuf interface that takes 32-bit int len arguments
345
   * so the function limits the maximum string size to INT32_MAX (2GB).
346
   * If the function is called with len == -1 then strlen is called to check
347
   * the string length is less than INT32_MAX (2GB)
348
   */
349
7.17k
  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX))
350
0
  {
351
0
    tok->err = json_tokener_error_size;
352
0
    return NULL;
353
0
  }
354
355
7.17k
#ifdef HAVE_USELOCALE
356
7.17k
  {
357
7.17k
    if (c_numeric_locale == (locale_t)0)
358
1
    {
359
1
      c_numeric_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
360
1
      if (c_numeric_locale == (locale_t)0)
361
0
      {
362
0
        tok->err = json_tokener_error_memory;
363
0
        return NULL;
364
0
      }
365
1
    }
366
7.17k
    uselocale(c_numeric_locale);
367
7.17k
  }
368
#elif defined(HAVE_SETLOCALE)
369
  {
370
    char *tmplocale;
371
    tmplocale = setlocale(LC_NUMERIC, NULL);
372
    if (tmplocale)
373
    {
374
      oldlocale = strdup(tmplocale);
375
      if (oldlocale == NULL)
376
      {
377
        tok->err = json_tokener_error_memory;
378
        return NULL;
379
      }
380
    }
381
    setlocale(LC_NUMERIC, "C");
382
  }
383
#endif
384
385
863k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
386
863k
  {
387
388
2.18M
  redo_char:
389
2.18M
    switch (state)
390
2.18M
    {
391
392
852k
    case json_tokener_state_eatws:
393
      /* Advance until we change state */
394
1.10M
      while (is_ws_char(c))
395
253k
      {
396
253k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
397
0
          goto out;
398
253k
      }
399
852k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
400
1.07k
      {
401
1.07k
        printbuf_reset(tok->pb);
402
1.07k
        printbuf_memappend_checked(tok->pb, &c, 1);
403
1.07k
        state = json_tokener_state_comment_start;
404
1.07k
      }
405
851k
      else
406
851k
      {
407
851k
        state = saved_state;
408
851k
        goto redo_char;
409
851k
      }
410
1.07k
      break;
411
412
154k
    case json_tokener_state_start:
413
154k
      switch (c)
414
154k
      {
415
52.1k
      case '{':
416
52.1k
        state = json_tokener_state_eatws;
417
52.1k
        saved_state = json_tokener_state_object_field_start;
418
52.1k
        current = json_object_new_object();
419
52.1k
        if (current == NULL)
420
0
        {
421
0
          tok->err = json_tokener_error_memory;
422
0
          goto out;
423
0
        }
424
52.1k
        break;
425
52.1k
      case '[':
426
11.0k
        state = json_tokener_state_eatws;
427
11.0k
        saved_state = json_tokener_state_array;
428
11.0k
        current = json_object_new_array();
429
11.0k
        if (current == NULL)
430
0
        {
431
0
          tok->err = json_tokener_error_memory;
432
0
          goto out;
433
0
        }
434
11.0k
        break;
435
11.0k
      case 'I':
436
14
      case 'i':
437
14
        state = json_tokener_state_inf;
438
14
        printbuf_reset(tok->pb);
439
14
        tok->st_pos = 0;
440
14
        goto redo_char;
441
140
      case 'N':
442
427
      case 'n':
443
427
        state = json_tokener_state_null; // or NaN
444
427
        printbuf_reset(tok->pb);
445
427
        tok->st_pos = 0;
446
427
        goto redo_char;
447
109
      case '\'':
448
109
        if (tok->flags & JSON_TOKENER_STRICT)
449
0
        {
450
          /* in STRICT mode only double-quote are allowed */
451
0
          tok->err = json_tokener_error_parse_unexpected;
452
0
          goto out;
453
0
        }
454
        /* FALLTHRU */
455
77.5k
      case '"':
456
77.5k
        state = json_tokener_state_string;
457
77.5k
        printbuf_reset(tok->pb);
458
77.5k
        tok->quote_char = c;
459
77.5k
        break;
460
25
      case 'T':
461
73
      case 't':
462
202
      case 'F':
463
329
      case 'f':
464
329
        state = json_tokener_state_boolean;
465
329
        printbuf_reset(tok->pb);
466
329
        tok->st_pos = 0;
467
329
        goto redo_char;
468
3.02k
      case '0':
469
5.85k
      case '1':
470
6.80k
      case '2':
471
7.19k
      case '3':
472
8.88k
      case '4':
473
9.62k
      case '5':
474
9.76k
      case '6':
475
9.93k
      case '7':
476
10.0k
      case '8':
477
10.4k
      case '9':
478
12.6k
      case '-':
479
12.6k
        state = json_tokener_state_number;
480
12.6k
        printbuf_reset(tok->pb);
481
12.6k
        tok->is_double = 0;
482
12.6k
        goto redo_char;
483
88
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
484
154k
      }
485
140k
      break;
486
487
152k
    case json_tokener_state_finish:
488
152k
      if (tok->depth == 0)
489
6.72k
        goto out;
490
145k
      obj = json_object_get(current);
491
145k
      json_tokener_reset_level(tok, tok->depth);
492
145k
      tok->depth--;
493
145k
      goto redo_char;
494
495
15
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
496
15
    {
497
      /* If we were guaranteed to have len set, then we could (usually) handle
498
       * the entire "Infinity" check in a single strncmp (strncasecmp), but
499
       * since len might be -1 (i.e. "read until \0"), we need to check it
500
       * a character at a time.
501
       * Trying to handle it both ways would make this code considerably more
502
       * complicated with likely little performance benefit.
503
       */
504
15
      int is_negative = 0;
505
506
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
507
37
      while (tok->st_pos < (int)json_inf_str_len)
508
37
      {
509
37
        char inf_char = *str;
510
37
        if (inf_char != json_inf_str[tok->st_pos] &&
511
29
            ((tok->flags & JSON_TOKENER_STRICT) ||
512
29
              inf_char != json_inf_str_invert[tok->st_pos])
513
37
           )
514
15
        {
515
15
          tok->err = json_tokener_error_parse_unexpected;
516
15
          goto out;
517
15
        }
518
22
        tok->st_pos++;
519
22
        (void)ADVANCE_CHAR(str, tok);
520
22
        if (!PEEK_CHAR(c, tok))
521
0
        {
522
          /* out of input chars, for now at least */
523
0
          goto out;
524
0
        }
525
22
      }
526
      /* We checked the full length of "Infinity", so create the object.
527
       * When handling -Infinity, the number parsing code will have dropped
528
       * the "-" into tok->pb for us, so check it now.
529
       */
530
0
      if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
531
0
      {
532
0
        is_negative = 1;
533
0
      }
534
0
      current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
535
0
      if (current == NULL)
536
0
      {
537
0
        tok->err = json_tokener_error_memory;
538
0
        goto out;
539
0
      }
540
0
      saved_state = json_tokener_state_finish;
541
0
      state = json_tokener_state_eatws;
542
0
      goto redo_char;
543
0
    }
544
0
    break;
545
1.94k
    case json_tokener_state_null: /* aka starts with 'n' */
546
1.94k
    {
547
1.94k
      int size;
548
1.94k
      int size_nan;
549
1.94k
      printbuf_memappend_checked(tok->pb, &c, 1);
550
1.94k
      size = json_min(tok->st_pos + 1, json_null_str_len);
551
1.94k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
552
1.94k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
553
1.94k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
554
424
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
555
1.52k
      {
556
1.52k
        if (tok->st_pos == json_null_str_len)
557
272
        {
558
272
          current = NULL;
559
272
          saved_state = json_tokener_state_finish;
560
272
          state = json_tokener_state_eatws;
561
272
          goto redo_char;
562
272
        }
563
1.52k
      }
564
424
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
565
424
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
566
22
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
567
402
      {
568
402
        if (tok->st_pos == json_nan_str_len)
569
133
        {
570
133
          current = json_object_new_double(NAN);
571
133
          if (current == NULL)
572
0
          {
573
0
            tok->err = json_tokener_error_memory;
574
0
            goto out;
575
0
          }
576
133
          saved_state = json_tokener_state_finish;
577
133
          state = json_tokener_state_eatws;
578
133
          goto redo_char;
579
133
        }
580
402
      }
581
22
      else
582
22
      {
583
22
        tok->err = json_tokener_error_parse_null;
584
22
        goto out;
585
22
      }
586
1.51k
      tok->st_pos++;
587
1.51k
    }
588
0
    break;
589
590
1.07k
    case json_tokener_state_comment_start:
591
1.07k
      if (c == '*')
592
272
      {
593
272
        state = json_tokener_state_comment;
594
272
      }
595
798
      else if (c == '/')
596
786
      {
597
786
        state = json_tokener_state_comment_eol;
598
786
      }
599
12
      else
600
12
      {
601
12
        tok->err = json_tokener_error_parse_comment;
602
12
        goto out;
603
12
      }
604
1.05k
      printbuf_memappend_checked(tok->pb, &c, 1);
605
1.05k
      break;
606
607
1.52k
    case json_tokener_state_comment:
608
1.52k
    {
609
      /* Advance until we change state */
610
1.52k
      const char *case_start = str;
611
24.3k
      while (c != '*')
612
22.8k
      {
613
22.8k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
614
27
        {
615
27
          printbuf_memappend_checked(tok->pb, case_start,
616
27
                                     str - case_start);
617
27
          goto out;
618
27
        }
619
22.8k
      }
620
1.49k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
621
1.49k
      state = json_tokener_state_comment_end;
622
1.49k
    }
623
0
    break;
624
625
786
    case json_tokener_state_comment_eol:
626
786
    {
627
      /* Advance until we change state */
628
786
      const char *case_start = str;
629
56.6k
      while (c != '\n')
630
55.9k
      {
631
55.9k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
632
46
        {
633
46
          printbuf_memappend_checked(tok->pb, case_start,
634
46
                                     str - case_start);
635
46
          goto out;
636
46
        }
637
55.9k
      }
638
740
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
639
740
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
640
740
      state = json_tokener_state_eatws;
641
740
    }
642
0
    break;
643
644
1.49k
    case json_tokener_state_comment_end:
645
1.49k
      printbuf_memappend_checked(tok->pb, &c, 1);
646
1.49k
      if (c == '/')
647
240
      {
648
240
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
649
240
        state = json_tokener_state_eatws;
650
240
      }
651
1.25k
      else
652
1.25k
      {
653
1.25k
        state = json_tokener_state_comment;
654
1.25k
      }
655
1.49k
      break;
656
657
124k
    case json_tokener_state_string:
658
124k
    {
659
      /* Advance until we change state */
660
124k
      const char *case_start = str;
661
1.85M
      while (1)
662
1.85M
      {
663
1.85M
        if (c == tok->quote_char)
664
77.4k
        {
665
77.4k
          printbuf_memappend_checked(tok->pb, case_start,
666
77.4k
                                     str - case_start);
667
77.4k
          current =
668
77.4k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
669
77.4k
          if (current == NULL)
670
0
          {
671
0
            tok->err = json_tokener_error_memory;
672
0
            goto out;
673
0
          }
674
77.4k
          saved_state = json_tokener_state_finish;
675
77.4k
          state = json_tokener_state_eatws;
676
77.4k
          break;
677
77.4k
        }
678
1.77M
        else if (c == '\\')
679
47.4k
        {
680
47.4k
          printbuf_memappend_checked(tok->pb, case_start,
681
47.4k
                                     str - case_start);
682
47.4k
          saved_state = json_tokener_state_string;
683
47.4k
          state = json_tokener_state_string_escape;
684
47.4k
          break;
685
47.4k
        }
686
1.73M
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
687
0
        {
688
          // Disallow control characters in strict mode
689
0
          tok->err = json_tokener_error_parse_string;
690
0
          goto out;
691
0
        }
692
1.73M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
693
40
        {
694
40
          printbuf_memappend_checked(tok->pb, case_start,
695
40
                                     str - case_start);
696
40
          goto out;
697
40
        }
698
1.73M
      }
699
124k
    }
700
124k
    break;
701
702
124k
    case json_tokener_state_string_escape:
703
56.1k
      switch (c)
704
56.1k
      {
705
10.8k
      case '"':
706
32.8k
      case '\\':
707
32.9k
      case '/':
708
32.9k
        printbuf_memappend_checked(tok->pb, &c, 1);
709
32.9k
        state = saved_state;
710
32.9k
        break;
711
940
      case 'b':
712
19.4k
      case 'n':
713
19.6k
      case 'r':
714
20.2k
      case 't':
715
20.4k
      case 'f':
716
20.4k
        if (c == 'b')
717
940
          printbuf_memappend_checked(tok->pb, "\b", 1);
718
19.5k
        else if (c == 'n')
719
18.4k
          printbuf_memappend_checked(tok->pb, "\n", 1);
720
1.08k
        else if (c == 'r')
721
266
          printbuf_memappend_checked(tok->pb, "\r", 1);
722
819
        else if (c == 't')
723
570
          printbuf_memappend_checked(tok->pb, "\t", 1);
724
249
        else if (c == 'f')
725
249
          printbuf_memappend_checked(tok->pb, "\f", 1);
726
20.4k
        state = saved_state;
727
20.4k
        break;
728
2.73k
      case 'u':
729
2.73k
        tok->ucs_char = 0;
730
2.73k
        tok->st_pos = 0;
731
2.73k
        state = json_tokener_state_escape_unicode;
732
2.73k
        break;
733
13
      default: tok->err = json_tokener_error_parse_string; goto out;
734
56.1k
      }
735
56.1k
      break;
736
737
      // ===================================================
738
739
56.1k
    case json_tokener_state_escape_unicode:
740
3.18k
    {
741
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
742
12.7k
      while (1)
743
12.7k
      {
744
12.7k
        if (!c || !is_hex_char(c))
745
13
        {
746
13
          tok->err = json_tokener_error_parse_string;
747
13
          goto out;
748
13
        }
749
12.7k
        tok->ucs_char |=
750
12.7k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
751
12.7k
        tok->st_pos++;
752
12.7k
        if (tok->st_pos >= 4)
753
3.17k
          break;
754
755
9.53k
        (void)ADVANCE_CHAR(str, tok);
756
9.53k
        if (!PEEK_CHAR(c, tok))
757
0
        {
758
          /*
759
           * We're out of characters in the current call to
760
           * json_tokener_parse(), but a subsequent call might
761
           * provide us with more, so leave our current state
762
           * as-is (including tok->high_surrogate) and return.
763
           */
764
0
          goto out;
765
0
        }
766
9.53k
      }
767
3.17k
      tok->st_pos = 0;
768
769
      /* Now, we have a full \uNNNN sequence in tok->ucs_char */
770
771
      /* If the *previous* sequence was a high surrogate ... */
772
3.17k
      if (tok->high_surrogate)
773
446
      {
774
446
        if (IS_LOW_SURROGATE(tok->ucs_char))
775
329
        {
776
          /* Recalculate the ucs_char, then fall thru to process normally */
777
329
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
778
329
                                                tok->ucs_char);
779
329
        }
780
117
        else
781
117
        {
782
          /* High surrogate was not followed by a low surrogate
783
           * Replace the high and process the rest normally
784
           */
785
117
          printbuf_memappend_checked(tok->pb,
786
117
                                     (char *)utf8_replacement_char, 3);
787
117
        }
788
446
        tok->high_surrogate = 0;
789
446
      }
790
791
3.17k
      if (tok->ucs_char < 0x80)
792
927
      {
793
927
        unsigned char unescaped_utf[1];
794
927
        unescaped_utf[0] = tok->ucs_char;
795
927
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
796
927
      }
797
2.24k
      else if (tok->ucs_char < 0x800)
798
39
      {
799
39
        unsigned char unescaped_utf[2];
800
39
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
801
39
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
802
39
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
803
39
      }
804
2.20k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
805
664
      {
806
        /*
807
         * The next two characters should be \u, HOWEVER,
808
         * we can't simply peek ahead here, because the
809
         * characters we need might not be passed to us
810
         * until a subsequent call to json_tokener_parse.
811
         * Instead, transition through a couple of states.
812
         * (now):
813
         *   _escape_unicode => _unicode_need_escape
814
         * (see a '\\' char):
815
         *   _unicode_need_escape => _unicode_need_u
816
         * (see a 'u' char):
817
         *   _unicode_need_u => _escape_unicode
818
         *      ...and we'll end up back around here.
819
         */
820
664
        tok->high_surrogate = tok->ucs_char;
821
664
        tok->ucs_char = 0;
822
664
        state = json_tokener_state_escape_unicode_need_escape;
823
664
        break;
824
664
      }
825
1.54k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
826
578
      {
827
        /* Got a low surrogate not preceded by a high */
828
578
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
829
578
      }
830
962
      else if (tok->ucs_char < 0x10000)
831
633
      {
832
633
        unsigned char unescaped_utf[3];
833
633
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
834
633
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
835
633
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
836
633
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
837
633
      }
838
329
      else if (tok->ucs_char < 0x110000)
839
329
      {
840
329
        unsigned char unescaped_utf[4];
841
329
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
842
329
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
843
329
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
844
329
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
845
329
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
846
329
      }
847
0
      else
848
0
      {
849
        /* Don't know what we got--insert the replacement char */
850
0
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
851
0
      }
852
2.50k
      state = saved_state; // i.e. _state_string or _state_object_field
853
2.50k
    }
854
0
    break;
855
856
664
    case json_tokener_state_escape_unicode_need_escape:
857
      // We get here after processing a high_surrogate
858
      // require a '\\' char
859
664
      if (!c || c != '\\')
860
134
      {
861
        /* Got a high surrogate without another sequence following
862
         * it.  Put a replacement char in for the high surrogate
863
         * and pop back up to _state_string or _state_object_field.
864
         */
865
134
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
866
134
        tok->high_surrogate = 0;
867
134
        tok->ucs_char = 0;
868
134
        tok->st_pos = 0;
869
134
        state = saved_state;
870
134
        goto redo_char;
871
134
      }
872
530
      state = json_tokener_state_escape_unicode_need_u;
873
530
      break;
874
875
530
    case json_tokener_state_escape_unicode_need_u:
876
      /* We already had a \ char, check that it's \u */
877
530
      if (!c || c != 'u')
878
82
      {
879
        /* Got a high surrogate with some non-unicode escape
880
         * sequence following it.
881
         * Put a replacement char in for the high surrogate
882
         * and handle the escape sequence normally.
883
         */
884
82
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
885
82
        tok->high_surrogate = 0;
886
82
        tok->ucs_char = 0;
887
82
        tok->st_pos = 0;
888
82
        state = json_tokener_state_string_escape;
889
82
        goto redo_char;
890
82
      }
891
448
      state = json_tokener_state_escape_unicode;
892
448
      break;
893
894
      // ===================================================
895
896
1.83k
    case json_tokener_state_boolean:
897
1.83k
    {
898
1.83k
      int size1, size2;
899
1.83k
      printbuf_memappend_checked(tok->pb, &c, 1);
900
1.83k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
901
1.83k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
902
1.83k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
903
1.83k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
904
1.51k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
905
317
      {
906
317
        if (tok->st_pos == json_true_str_len)
907
60
        {
908
60
          current = json_object_new_boolean(1);
909
60
          if (current == NULL)
910
0
          {
911
0
            tok->err = json_tokener_error_memory;
912
0
            goto out;
913
0
          }
914
60
          saved_state = json_tokener_state_finish;
915
60
          state = json_tokener_state_eatws;
916
60
          goto redo_char;
917
60
        }
918
317
      }
919
1.51k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
920
1.51k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
921
24
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
922
1.49k
      {
923
1.49k
        if (tok->st_pos == json_false_str_len)
924
245
        {
925
245
          current = json_object_new_boolean(0);
926
245
          if (current == NULL)
927
0
          {
928
0
            tok->err = json_tokener_error_memory;
929
0
            goto out;
930
0
          }
931
245
          saved_state = json_tokener_state_finish;
932
245
          state = json_tokener_state_eatws;
933
245
          goto redo_char;
934
245
        }
935
1.49k
      }
936
24
      else
937
24
      {
938
24
        tok->err = json_tokener_error_parse_boolean;
939
24
        goto out;
940
24
      }
941
1.50k
      tok->st_pos++;
942
1.50k
    }
943
0
    break;
944
945
12.6k
    case json_tokener_state_number:
946
12.6k
    {
947
      /* Advance until we change state */
948
12.6k
      const char *case_start = str;
949
12.6k
      int case_len = 0;
950
12.6k
      int is_exponent = 0;
951
12.6k
      int neg_sign_ok = 1;
952
12.6k
      int pos_sign_ok = 0;
953
12.6k
      if (printbuf_length(tok->pb) > 0)
954
0
      {
955
        /* We don't save all state from the previous incremental parse
956
           so we need to re-generate it based on the saved string so far.
957
         */
958
0
        char *e_loc = strchr(tok->pb->buf, 'e');
959
0
        if (!e_loc)
960
0
          e_loc = strchr(tok->pb->buf, 'E');
961
0
        if (e_loc)
962
0
        {
963
0
          char *last_saved_char =
964
0
              &tok->pb->buf[printbuf_length(tok->pb) - 1];
965
0
          is_exponent = 1;
966
0
          pos_sign_ok = neg_sign_ok = 1;
967
          /* If the "e" isn't at the end, we can't start with a '-' */
968
0
          if (e_loc != last_saved_char)
969
0
          {
970
0
            neg_sign_ok = 0;
971
0
            pos_sign_ok = 0;
972
0
          }
973
          // else leave it set to 1, i.e. start of the new input
974
0
        }
975
0
      }
976
977
90.0k
      while (c && ((c >= '0' && c <= '9') ||
978
16.2k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
979
15.7k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
980
13.0k
                   (!tok->is_double && c == '.')))
981
77.4k
      {
982
77.4k
        pos_sign_ok = neg_sign_ok = 0;
983
77.4k
        ++case_len;
984
985
        /* non-digit characters checks */
986
        /* note: since the main loop condition to get here was
987
         * an input starting with 0-9 or '-', we are
988
         * protected from input starting with '.' or
989
         * e/E.
990
         */
991
77.4k
        switch (c)
992
77.4k
        {
993
520
        case '.':
994
520
          tok->is_double = 1;
995
520
          pos_sign_ok = 1;
996
520
          neg_sign_ok = 1;
997
520
          break;
998
476
        case 'e': /* FALLTHRU */
999
508
        case 'E':
1000
508
          is_exponent = 1;
1001
508
          tok->is_double = 1;
1002
          /* the exponent part can begin with a negative sign */
1003
508
          pos_sign_ok = neg_sign_ok = 1;
1004
508
          break;
1005
76.3k
        default: break;
1006
77.4k
        }
1007
1008
77.4k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1009
0
        {
1010
0
          printbuf_memappend_checked(tok->pb, case_start, case_len);
1011
0
          goto out;
1012
0
        }
1013
77.4k
      }
1014
      /*
1015
        Now we know c isn't a valid number char, but check whether
1016
        it might have been intended to be, and return a potentially
1017
        more understandable error right away.
1018
        However, if we're at the top-level, use the number as-is
1019
        because c can be part of a new object to parse on the
1020
        next call to json_tokener_parse().
1021
       */
1022
12.6k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1023
997
          c != 'I' && c != 'i' && !is_ws_char(c))
1024
36
      {
1025
36
        tok->err = json_tokener_error_parse_number;
1026
36
        goto out;
1027
36
      }
1028
12.5k
      if (case_len > 0)
1029
12.5k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1030
1031
      // Check for -Infinity
1032
12.5k
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1033
1
      {
1034
1
        state = json_tokener_state_inf;
1035
1
        tok->st_pos = 0;
1036
1
        goto redo_char;
1037
1
      }
1038
12.5k
      if (tok->flags & JSON_TOKENER_STRICT)
1039
0
      {
1040
        /* Check the accumulated text against the RFC 8259 grammar:
1041
         *
1042
         *   number = [ minus ] int [ frac ] [ exp ]
1043
         *   int    = zero / ( digit1-9 *DIGIT )
1044
         *   frac   = decimal-point 1*DIGIT
1045
         *   exp    = e [ minus / plus ] 1*DIGIT
1046
         *
1047
         * so the integer part is mandatory and may not carry a
1048
         * leading zero, and both the fraction and the exponent
1049
         * need at least one digit of their own. That rejects
1050
         * "01", ".5", "-.123", "1.", "2.e3" and "1e", while
1051
         * "0", "-0", "0.5" and "2e3" stay valid.
1052
         */
1053
0
        const char *num = tok->pb->buf;
1054
0
        if (*num == '-')
1055
0
          num++;
1056
0
        if (*num == '0')
1057
0
        {
1058
0
          num++;
1059
0
          if (*num >= '0' && *num <= '9')
1060
0
          {
1061
0
            tok->err = json_tokener_error_parse_number;
1062
0
            goto out;
1063
0
          }
1064
0
        }
1065
0
        else if (*num >= '1' && *num <= '9')
1066
0
        {
1067
0
          while (*num >= '0' && *num <= '9')
1068
0
            num++;
1069
0
        }
1070
0
        else
1071
0
        {
1072
          /* no integer part at all, e.g. ".5" or "-.123" */
1073
0
          tok->err = json_tokener_error_parse_number;
1074
0
          goto out;
1075
0
        }
1076
0
        if (*num == '.')
1077
0
        {
1078
0
          num++;
1079
0
          if (!(*num >= '0' && *num <= '9'))
1080
0
          {
1081
0
            tok->err = json_tokener_error_parse_number;
1082
0
            goto out;
1083
0
          }
1084
0
          while (*num >= '0' && *num <= '9')
1085
0
            num++;
1086
0
        }
1087
0
        if (*num == 'e' || *num == 'E')
1088
0
        {
1089
0
          num++;
1090
0
          if (*num == '+' || *num == '-')
1091
0
            num++;
1092
0
          if (!(*num >= '0' && *num <= '9'))
1093
0
          {
1094
0
            tok->err = json_tokener_error_parse_number;
1095
0
            goto out;
1096
0
          }
1097
0
          while (*num >= '0' && *num <= '9')
1098
0
            num++;
1099
0
        }
1100
0
        if (*num != '\0')
1101
0
        {
1102
0
          tok->err = json_tokener_error_parse_number;
1103
0
          goto out;
1104
0
        }
1105
0
      }
1106
12.5k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1107
597
      {
1108
        /* Trim some chars off the end, to allow things
1109
           like "123e+" to parse ok. */
1110
1.20k
        while (printbuf_length(tok->pb) > 1)
1111
1.18k
        {
1112
1.18k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1113
1.18k
          if (last_char != 'e' && last_char != 'E' &&
1114
853
              last_char != '-' && last_char != '+')
1115
572
          {
1116
572
            break;
1117
572
          }
1118
612
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1119
612
          printbuf_length(tok->pb)--;
1120
612
        }
1121
597
      }
1122
12.5k
    }
1123
0
      {
1124
12.5k
        int64_t num64;
1125
12.5k
        uint64_t numuint64;
1126
12.5k
        double numd;
1127
12.5k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1128
1.67k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1129
1.67k
        {
1130
1.67k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1131
0
          {
1132
0
            tok->err = json_tokener_error_parse_number;
1133
0
            goto out;
1134
0
          }
1135
1.67k
          current = json_object_new_int64(num64);
1136
1.67k
          if (current == NULL)
1137
0
          {
1138
0
            tok->err = json_tokener_error_memory;
1139
0
            goto out;
1140
0
          }
1141
1.67k
        }
1142
10.9k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1143
10.3k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1144
10.3k
        {
1145
10.3k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1146
0
          {
1147
0
            tok->err = json_tokener_error_parse_number;
1148
0
            goto out;
1149
0
          }
1150
10.3k
          if (numuint64 <= INT64_MAX)
1151
9.79k
          {
1152
9.79k
            num64 = (int64_t)numuint64;
1153
9.79k
            current = json_object_new_int64(num64);
1154
9.79k
            if (current == NULL)
1155
0
            {
1156
0
              tok->err = json_tokener_error_memory;
1157
0
              goto out;
1158
0
            }
1159
9.79k
          }
1160
504
          else
1161
504
          {
1162
504
            current = json_object_new_uint64(numuint64);
1163
504
            if (current == NULL)
1164
0
            {
1165
0
              tok->err = json_tokener_error_memory;
1166
0
              goto out;
1167
0
            }
1168
504
          }
1169
10.3k
        }
1170
601
        else if (tok->is_double &&
1171
597
                 json_tokener_parse_double(
1172
597
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1173
595
        {
1174
595
          current = json_object_new_double_s(numd, tok->pb->buf);
1175
595
          if (current == NULL)
1176
0
          {
1177
0
            tok->err = json_tokener_error_memory;
1178
0
            goto out;
1179
0
          }
1180
595
        }
1181
6
        else
1182
6
        {
1183
6
          tok->err = json_tokener_error_parse_number;
1184
6
          goto out;
1185
6
        }
1186
12.5k
        saved_state = json_tokener_state_finish;
1187
12.5k
        state = json_tokener_state_eatws;
1188
12.5k
        goto redo_char;
1189
12.5k
      }
1190
0
      break;
1191
1192
20.9k
    case json_tokener_state_array_after_sep:
1193
31.9k
    case json_tokener_state_array:
1194
31.9k
      if (c == ']')
1195
462
      {
1196
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1197
462
        json_object_array_shrink(current, 0);
1198
1199
462
        if (state == json_tokener_state_array_after_sep &&
1200
27
            (tok->flags & JSON_TOKENER_STRICT))
1201
0
        {
1202
0
          tok->err = json_tokener_error_parse_unexpected;
1203
0
          goto out;
1204
0
        }
1205
462
        saved_state = json_tokener_state_finish;
1206
462
        state = json_tokener_state_eatws;
1207
462
      }
1208
31.5k
      else
1209
31.5k
      {
1210
31.5k
        if (tok->depth >= tok->max_depth - 1)
1211
1
        {
1212
1
          tok->err = json_tokener_error_depth;
1213
1
          goto out;
1214
1
        }
1215
31.5k
        state = json_tokener_state_array_add;
1216
31.5k
        tok->depth++;
1217
31.5k
        json_tokener_reset_level(tok, tok->depth);
1218
31.5k
        goto redo_char;
1219
31.5k
      }
1220
462
      break;
1221
1222
31.0k
    case json_tokener_state_array_add:
1223
31.0k
      if (json_object_array_add(current, obj) != 0)
1224
0
      {
1225
0
        tok->err = json_tokener_error_memory;
1226
0
        goto out;
1227
0
      }
1228
31.0k
      saved_state = json_tokener_state_array_sep;
1229
31.0k
      state = json_tokener_state_eatws;
1230
31.0k
      goto redo_char;
1231
1232
31.0k
    case json_tokener_state_array_sep:
1233
31.0k
      if (c == ']')
1234
10.0k
      {
1235
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1236
10.0k
        json_object_array_shrink(current, 0);
1237
1238
10.0k
        saved_state = json_tokener_state_finish;
1239
10.0k
        state = json_tokener_state_eatws;
1240
10.0k
      }
1241
20.9k
      else if (c == ',')
1242
20.9k
      {
1243
20.9k
        saved_state = json_tokener_state_array_after_sep;
1244
20.9k
        state = json_tokener_state_eatws;
1245
20.9k
      }
1246
25
      else
1247
25
      {
1248
25
        tok->err = json_tokener_error_parse_array;
1249
25
        goto out;
1250
25
      }
1251
31.0k
      break;
1252
1253
52.1k
    case json_tokener_state_object_field_start:
1254
135k
    case json_tokener_state_object_field_start_after_sep:
1255
135k
      if (c == '}')
1256
20.1k
      {
1257
20.1k
        if (state == json_tokener_state_object_field_start_after_sep &&
1258
3
            (tok->flags & JSON_TOKENER_STRICT))
1259
0
        {
1260
0
          tok->err = json_tokener_error_parse_unexpected;
1261
0
          goto out;
1262
0
        }
1263
20.1k
        saved_state = json_tokener_state_finish;
1264
20.1k
        state = json_tokener_state_eatws;
1265
20.1k
      }
1266
115k
      else if (c == '"' || c == '\'')
1267
115k
      {
1268
115k
        tok->quote_char = c;
1269
115k
        printbuf_reset(tok->pb);
1270
115k
        state = json_tokener_state_object_field;
1271
115k
      }
1272
19
      else
1273
19
      {
1274
19
        tok->err = json_tokener_error_parse_object_key_name;
1275
19
        goto out;
1276
19
      }
1277
135k
      break;
1278
1279
135k
    case json_tokener_state_object_field:
1280
124k
    {
1281
      /* Advance until we change state */
1282
124k
      const char *case_start = str;
1283
1.01M
      while (1)
1284
1.01M
      {
1285
1.01M
        if (c == tok->quote_char)
1286
115k
        {
1287
115k
          printbuf_memappend_checked(tok->pb, case_start,
1288
115k
                                     str - case_start);
1289
115k
          obj_field_name = strdup(tok->pb->buf);
1290
115k
          if (obj_field_name == NULL)
1291
0
          {
1292
0
            tok->err = json_tokener_error_memory;
1293
0
            goto out;
1294
0
          }
1295
115k
          saved_state = json_tokener_state_object_field_end;
1296
115k
          state = json_tokener_state_eatws;
1297
115k
          break;
1298
115k
        }
1299
897k
        else if (c == '\\')
1300
8.64k
        {
1301
8.64k
          printbuf_memappend_checked(tok->pb, case_start,
1302
8.64k
                                     str - case_start);
1303
8.64k
          saved_state = json_tokener_state_object_field;
1304
8.64k
          state = json_tokener_state_string_escape;
1305
8.64k
          break;
1306
8.64k
        }
1307
888k
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
1308
0
        {
1309
          // Disallow control characters in strict mode
1310
0
          tok->err = json_tokener_error_parse_string;
1311
0
          goto out;
1312
0
        }
1313
888k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1314
24
        {
1315
24
          printbuf_memappend_checked(tok->pb, case_start,
1316
24
                                     str - case_start);
1317
24
          goto out;
1318
24
        }
1319
888k
      }
1320
124k
    }
1321
124k
    break;
1322
1323
124k
    case json_tokener_state_object_field_end:
1324
115k
      if (c == ':')
1325
115k
      {
1326
115k
        saved_state = json_tokener_state_object_value;
1327
115k
        state = json_tokener_state_eatws;
1328
115k
      }
1329
18
      else
1330
18
      {
1331
18
        tok->err = json_tokener_error_parse_object_key_sep;
1332
18
        goto out;
1333
18
      }
1334
115k
      break;
1335
1336
115k
    case json_tokener_state_object_value:
1337
115k
      if (tok->depth >= tok->max_depth - 1)
1338
0
      {
1339
0
        tok->err = json_tokener_error_depth;
1340
0
        goto out;
1341
0
      }
1342
115k
      state = json_tokener_state_object_value_add;
1343
115k
      tok->depth++;
1344
115k
      json_tokener_reset_level(tok, tok->depth);
1345
115k
      goto redo_char;
1346
1347
114k
    case json_tokener_state_object_value_add:
1348
114k
      if (json_object_object_add(current, obj_field_name, obj) != 0)
1349
0
      {
1350
0
        tok->err = json_tokener_error_memory;
1351
0
        goto out;
1352
0
      }
1353
114k
      free(obj_field_name);
1354
114k
      obj_field_name = NULL;
1355
114k
      saved_state = json_tokener_state_object_sep;
1356
114k
      state = json_tokener_state_eatws;
1357
114k
      goto redo_char;
1358
1359
114k
    case json_tokener_state_object_sep:
1360
      /* { */
1361
114k
      if (c == '}')
1362
31.2k
      {
1363
31.2k
        saved_state = json_tokener_state_finish;
1364
31.2k
        state = json_tokener_state_eatws;
1365
31.2k
      }
1366
83.6k
      else if (c == ',')
1367
83.6k
      {
1368
83.6k
        saved_state = json_tokener_state_object_field_start_after_sep;
1369
83.6k
        state = json_tokener_state_eatws;
1370
83.6k
      }
1371
16
      else
1372
16
      {
1373
16
        tok->err = json_tokener_error_parse_object_value_sep;
1374
16
        goto out;
1375
16
      }
1376
114k
      break;
1377
2.18M
    }
1378
856k
    (void)ADVANCE_CHAR(str, tok);
1379
856k
    if (!c) // This is the char *before* advancing
1380
5
      break;
1381
856k
  } /* while(PEEK_CHAR) */
1382
1383
7.17k
out:
1384
7.17k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1385
0
  {
1386
0
    tok->err = json_tokener_error_parse_utf8_string;
1387
0
  }
1388
7.17k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1389
58
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1390
58
          JSON_TOKENER_STRICT)
1391
0
  {
1392
    /* unexpected char after JSON data */
1393
0
    tok->err = json_tokener_error_parse_unexpected;
1394
0
  }
1395
7.17k
  if (!c)
1396
6.89k
  {
1397
    /* We hit an eof char (0) */
1398
6.89k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1399
192
      tok->err = json_tokener_error_parse_eof;
1400
6.89k
  }
1401
1402
7.17k
#ifdef HAVE_USELOCALE
1403
7.17k
  uselocale(oldlocale);
1404
#elif defined(HAVE_SETLOCALE)
1405
  setlocale(LC_NUMERIC, oldlocale);
1406
  free(oldlocale);
1407
#endif
1408
1409
7.17k
  if (tok->err == json_tokener_success)
1410
6.76k
  {
1411
6.76k
    json_object *ret = json_object_get(current);
1412
6.76k
    int ii;
1413
1414
    /* Partially reset, so we parse additional objects on subsequent calls. */
1415
13.5k
    for (ii = tok->depth; ii >= 0; ii--)
1416
6.81k
      json_tokener_reset_level(tok, ii);
1417
6.76k
    return ret;
1418
6.76k
  }
1419
1420
411
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1421
411
           tok->char_offset);
1422
411
  return NULL;
1423
7.17k
}
1424
1425
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes)
1426
0
{
1427
0
  unsigned char chr = c;
1428
0
  if (*nBytes == 0)
1429
0
  {
1430
0
    if (chr >= 0x80)
1431
0
    {
1432
0
      if ((chr & 0xe0) == 0xc0)
1433
0
        *nBytes = 1;
1434
0
      else if ((chr & 0xf0) == 0xe0)
1435
0
        *nBytes = 2;
1436
0
      else if ((chr & 0xf8) == 0xf0)
1437
0
        *nBytes = 3;
1438
0
      else
1439
0
        return 0;
1440
0
    }
1441
0
  }
1442
0
  else
1443
0
  {
1444
0
    if ((chr & 0xC0) != 0x80)
1445
0
      return 0;
1446
0
    (*nBytes)--;
1447
0
  }
1448
0
  return 1;
1449
0
}
1450
1451
void json_tokener_set_flags(struct json_tokener *tok, int flags)
1452
0
{
1453
0
  tok->flags = flags;
1454
0
}
1455
1456
size_t json_tokener_get_parse_end(struct json_tokener *tok)
1457
0
{
1458
0
  assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */
1459
0
  return (size_t)tok->char_offset;
1460
0
}
1461
1462
static int json_tokener_parse_double(const char *buf, int len, double *retval)
1463
597
{
1464
597
  char *end;
1465
597
  *retval = strtod(buf, &end);
1466
597
  if (buf + len == end)
1467
595
    return 0; // It worked
1468
2
  return 1;
1469
597
}
1470
1471
#ifdef HAVE_USELOCALE
1472
/* Release the static C-numeric locale when the library is unloaded.
1473
 * This keeps Valgrind clean.
1474
 */
1475
#if defined(__GNUC__) || defined(__clang__)
1476
#define JSON_TOKENER_DESTRUCTOR __attribute__((destructor))
1477
#elif defined(_WIN32) || defined(_WIN64)
1478
#include <windows.h>
1479
1480
// Windows implementation using DllMain
1481
// Executed when FreeLibrary is called or the process exits
1482
#define JSON_TOKENER_DESTRUCTOR \
1483
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) \
1484
{ \
1485
  if (ul_reason_for_call == DLL_PROCESS_DETACH) \
1486
  { \
1487
    json_tokener_locale_fini(); \
1488
  } \
1489
  return TRUE; \
1490
}
1491
#endif
1492
1493
#ifdef JSON_TOKENER_DESTRUCTOR
1494
JSON_TOKENER_DESTRUCTOR
1495
static void json_tokener_locale_fini(void)
1496
0
{
1497
0
  if (c_numeric_locale != (locale_t)0)
1498
0
  {
1499
0
    freelocale(c_numeric_locale);
1500
0
    c_numeric_locale = (locale_t)0;
1501
0
  }
1502
0
}
1503
#endif
1504
1505
#endif /* HAVE_USELOCALE */