Coverage Report

Created: 2026-04-11 06:29

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
23.1k
#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.68M
{
71
1.68M
  return c == ' '
72
1.53M
      || c == '\t'
73
1.51M
      || c == '\n'
74
1.51M
      || c == '\r';
75
1.68M
}
76
77
static inline int is_hex_char(char c)
78
23.2k
{
79
23.2k
  return (c >= '0' && c <= '9')
80
10.5k
      || (c >= 'A' && c <= 'F')
81
2.04k
      || (c >= 'a' && c <= 'f');
82
23.2k
}
83
84
/* Use C99 NAN by default; if not available, nan("") should work too. */
85
#ifndef NAN
86
#define NAN nan("")
87
#endif /* !NAN */
88
89
static const char json_null_str[] = "null";
90
static const int json_null_str_len = sizeof(json_null_str) - 1;
91
static const char json_inf_str[] = "Infinity";
92
/* Swapped case "Infinity" to avoid need to call tolower() on input chars: */
93
static const char json_inf_str_invert[] = "iNFINITY";
94
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
95
static const char json_nan_str[] = "NaN";
96
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
97
static const char json_true_str[] = "true";
98
static const int json_true_str_len = sizeof(json_true_str) - 1;
99
static const char json_false_str[] = "false";
100
static const int json_false_str_len = sizeof(json_false_str) - 1;
101
102
/* clang-format off */
103
static const char *json_tokener_errors[] = {
104
  "success",
105
  "continue",
106
  "nesting too deep",
107
  "unexpected end of data",
108
  "unexpected character",
109
  "null expected",
110
  "boolean expected",
111
  "number expected",
112
  "array value separator ',' expected",
113
  "quoted object property name expected",
114
  "object property name separator ':' expected",
115
  "object value separator ',' expected",
116
  "invalid string sequence",
117
  "expected comment",
118
  "invalid utf-8 string",
119
  "buffer size overflow",
120
  "out of memory"
121
};
122
/* clang-format on */
123
124
/**
125
 * validete the utf-8 string in strict model.
126
 * if not utf-8 format, return err.
127
 */
128
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes);
129
130
static int json_tokener_parse_double(const char *buf, int len, double *retval);
131
132
const char *json_tokener_error_desc(enum json_tokener_error jerr)
133
2.19k
{
134
2.19k
  int jerr_int = (int)jerr;
135
2.19k
  if (jerr_int < 0 ||
136
2.19k
      jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
137
0
    return "Unknown error, "
138
0
           "invalid json_tokener_error value passed to json_tokener_error_desc()";
139
2.19k
  return json_tokener_errors[jerr];
140
2.19k
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
4.38k
{
144
4.38k
  return tok->err;
145
4.38k
}
146
147
/* Stuff for decoding unicode sequences */
148
4.28k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
3.51k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
643
#define DECODE_SURROGATE_PAIR(hi, lo) ((((hi)&0x3FF) << 10) + ((lo)&0x3FF) + 0x10000)
151
static unsigned char utf8_replacement_char[3] = {0xEF, 0xBF, 0xBD};
152
153
struct json_tokener *json_tokener_new_ex(int depth)
154
9.78k
{
155
9.78k
  struct json_tokener *tok;
156
157
9.78k
  if (depth < 1)
158
0
    return NULL;
159
160
9.78k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
9.78k
  if (!tok)
162
0
    return NULL;
163
9.78k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
9.78k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
9.78k
  tok->pb = printbuf_new();
170
9.78k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
9.78k
  tok->max_depth = depth;
177
9.78k
  json_tokener_reset(tok);
178
9.78k
  return tok;
179
9.78k
}
180
181
struct json_tokener *json_tokener_new(void)
182
9.78k
{
183
9.78k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
9.78k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
9.78k
{
188
9.78k
  if (!tok)
189
0
    return;
190
9.78k
  json_tokener_reset(tok);
191
9.78k
  if (tok->pb)
192
9.78k
    printbuf_free(tok->pb);
193
9.78k
  free(tok->stack);
194
9.78k
  free(tok);
195
9.78k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
644k
{
199
644k
  tok->stack[depth].state = json_tokener_state_eatws;
200
644k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
644k
  json_object_put(tok->stack[depth].current);
202
644k
  tok->stack[depth].current = NULL;
203
644k
  free(tok->stack[depth].obj_field_name);
204
644k
  tok->stack[depth].obj_field_name = NULL;
205
644k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
19.5k
{
209
19.5k
  int i;
210
19.5k
  if (!tok)
211
0
    return;
212
213
42.8k
  for (i = tok->depth; i >= 0; i--)
214
23.3k
    json_tokener_reset_level(tok, i);
215
19.5k
  tok->depth = 0;
216
19.5k
  tok->err = json_tokener_success;
217
19.5k
}
218
219
struct json_object *json_tokener_parse(const char *str)
220
0
{
221
0
  enum json_tokener_error jerr_ignored;
222
0
  struct json_object *obj;
223
0
  obj = json_tokener_parse_verbose(str, &jerr_ignored);
224
0
  return obj;
225
0
}
226
227
struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
228
0
{
229
0
  struct json_tokener *tok;
230
0
  struct json_object *obj;
231
232
0
  tok = json_tokener_new();
233
0
  if (!tok)
234
0
  {
235
0
    *error = json_tokener_error_memory;
236
0
    return NULL;
237
0
  }
238
0
  obj = json_tokener_parse_ex(tok, str, -1);
239
0
  *error = tok->err;
240
0
  if (tok->err != json_tokener_success
241
#if 0
242
    /* This would be a more sensible default, and cause parsing
243
     * things like "null123" to fail when the caller can't know
244
     * where the parsing left off, but starting to fail would
245
     * be a notable behaviour change.  Save for a 1.0 release.
246
     */
247
      || json_tokener_get_parse_end(tok) != strlen(str)
248
#endif
249
0
  )
250
251
0
  {
252
0
    if (obj != NULL)
253
0
      json_object_put(obj);
254
0
    obj = NULL;
255
0
  }
256
257
0
  json_tokener_free(tok);
258
0
  return obj;
259
0
}
260
261
7.44M
#define state tok->stack[tok->depth].state
262
2.81M
#define saved_state tok->stack[tok->depth].saved_state
263
1.24M
#define current tok->stack[tok->depth].current
264
605k
#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
6.04M
  (((tok)->char_offset == len)                                         \
286
6.04M
       ? (((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
6.04M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
6.04M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
6.04M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
6.04M
              : (((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
10.7M
#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
561k
  do {                                                  \
308
561k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
561k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
561k
  } while (0)
314
315
/* End optimization macro defs */
316
317
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
318
9.78k
{
319
9.78k
  struct json_object *obj = NULL;
320
9.78k
  char c = '\1';
321
9.78k
  unsigned int nBytes = 0;
322
9.78k
  unsigned int *nBytesp = &nBytes;
323
324
9.78k
#ifdef HAVE_USELOCALE
325
9.78k
  locale_t oldlocale = uselocale(NULL);
326
9.78k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
9.78k
  tok->char_offset = 0;
332
9.78k
  tok->err = json_tokener_success;
333
334
  /* this interface is presently not 64-bit clean due to the int len argument
335
   * and the internal printbuf interface that takes 32-bit int len arguments
336
   * so the function limits the maximum string size to INT32_MAX (2GB).
337
   * If the function is called with len == -1 then strlen is called to check
338
   * the string length is less than INT32_MAX (2GB)
339
   */
340
9.78k
  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX))
341
0
  {
342
0
    tok->err = json_tokener_error_size;
343
0
    return NULL;
344
0
  }
345
346
9.78k
#ifdef HAVE_USELOCALE
347
9.78k
  {
348
9.78k
#ifdef HAVE_DUPLOCALE
349
9.78k
    locale_t duploc = duplocale(oldlocale);
350
9.78k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
9.78k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
9.78k
    if (newloc == NULL)
360
0
    {
361
0
      tok->err = json_tokener_error_memory;
362
0
#ifdef HAVE_DUPLOCALE
363
0
      freelocale(duploc);
364
0
#endif
365
0
      return NULL;
366
0
    }
367
#ifdef NEWLOCALE_NEEDS_FREELOCALE
368
#ifdef HAVE_DUPLOCALE
369
    // Older versions of FreeBSD (<12.4) don't free the locale
370
    // passed to newlocale(), so do it here
371
    freelocale(duploc);
372
#endif
373
#endif
374
9.78k
    uselocale(newloc);
375
9.78k
  }
376
#elif defined(HAVE_SETLOCALE)
377
  {
378
    char *tmplocale;
379
    tmplocale = setlocale(LC_NUMERIC, NULL);
380
    if (tmplocale)
381
    {
382
      oldlocale = strdup(tmplocale);
383
      if (oldlocale == NULL)
384
      {
385
        tok->err = json_tokener_error_memory;
386
        return NULL;
387
      }
388
    }
389
    setlocale(LC_NUMERIC, "C");
390
  }
391
#endif
392
393
1.11M
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
1.11M
  {
395
396
3.89M
  redo_char:
397
3.89M
    switch (state)
398
3.89M
    {
399
400
1.51M
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
1.68M
      while (is_ws_char(c))
403
173k
      {
404
173k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
173k
      }
407
1.51M
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
2.53k
      {
409
2.53k
        printbuf_reset(tok->pb);
410
2.53k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
2.53k
        state = json_tokener_state_comment_start;
412
2.53k
      }
413
1.50M
      else
414
1.50M
      {
415
1.50M
        state = saved_state;
416
1.50M
        goto redo_char;
417
1.50M
      }
418
2.53k
      break;
419
420
318k
    case json_tokener_state_start:
421
318k
      switch (c)
422
318k
      {
423
53.9k
      case '{':
424
53.9k
        state = json_tokener_state_eatws;
425
53.9k
        saved_state = json_tokener_state_object_field_start;
426
53.9k
        current = json_object_new_object();
427
53.9k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
53.9k
        break;
433
53.9k
      case '[':
434
14.5k
        state = json_tokener_state_eatws;
435
14.5k
        saved_state = json_tokener_state_array;
436
14.5k
        current = json_object_new_array();
437
14.5k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
14.5k
        break;
443
14.5k
      case 'I':
444
649
      case 'i':
445
649
        state = json_tokener_state_inf;
446
649
        printbuf_reset(tok->pb);
447
649
        tok->st_pos = 0;
448
649
        goto redo_char;
449
1.04k
      case 'N':
450
13.9k
      case 'n':
451
13.9k
        state = json_tokener_state_null; // or NaN
452
13.9k
        printbuf_reset(tok->pb);
453
13.9k
        tok->st_pos = 0;
454
13.9k
        goto redo_char;
455
447
      case '\'':
456
447
        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
73.7k
      case '"':
464
73.7k
        state = json_tokener_state_string;
465
73.7k
        printbuf_reset(tok->pb);
466
73.7k
        tok->quote_char = c;
467
73.7k
        break;
468
641
      case 'T':
469
1.13k
      case 't':
470
1.26k
      case 'F':
471
1.85k
      case 'f':
472
1.85k
        state = json_tokener_state_boolean;
473
1.85k
        printbuf_reset(tok->pb);
474
1.85k
        tok->st_pos = 0;
475
1.85k
        goto redo_char;
476
23.5k
      case '0':
477
31.9k
      case '1':
478
35.7k
      case '2':
479
37.8k
      case '3':
480
40.5k
      case '4':
481
151k
      case '5':
482
152k
      case '6':
483
153k
      case '7':
484
154k
      case '8':
485
155k
      case '9':
486
159k
      case '-':
487
159k
        state = json_tokener_state_number;
488
159k
        printbuf_reset(tok->pb);
489
159k
        tok->is_double = 0;
490
159k
        goto redo_char;
491
136
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
318k
      }
493
142k
      break;
494
495
312k
    case json_tokener_state_finish:
496
312k
      if (tok->depth == 0)
497
7.49k
        goto out;
498
304k
      obj = json_object_get(current);
499
304k
      json_tokener_reset_level(tok, tok->depth);
500
304k
      tok->depth--;
501
304k
      goto redo_char;
502
503
1.07k
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
1.07k
    {
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
1.07k
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
9.07k
      while (tok->st_pos < (int)json_inf_str_len)
516
8.09k
      {
517
8.09k
        char inf_char = *str;
518
8.09k
        if (inf_char != json_inf_str[tok->st_pos] &&
519
3.56k
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
3.56k
              inf_char != json_inf_str_invert[tok->st_pos])
521
8.09k
           )
522
104
        {
523
104
          tok->err = json_tokener_error_parse_unexpected;
524
104
          goto out;
525
104
        }
526
7.99k
        tok->st_pos++;
527
7.99k
        (void)ADVANCE_CHAR(str, tok);
528
7.99k
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
7.99k
      }
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
974
      if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
539
403
      {
540
403
        is_negative = 1;
541
403
      }
542
974
      current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
543
974
      if (current == NULL)
544
0
      {
545
0
        tok->err = json_tokener_error_memory;
546
0
        goto out;
547
0
      }
548
974
      saved_state = json_tokener_state_finish;
549
974
      state = json_tokener_state_eatws;
550
974
      goto redo_char;
551
974
    }
552
0
    break;
553
68.8k
    case json_tokener_state_null: /* aka starts with 'n' */
554
68.8k
    {
555
68.8k
      int size;
556
68.8k
      int size_nan;
557
68.8k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
68.8k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
68.8k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
68.8k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
68.8k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
1.57k
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
67.2k
      {
564
67.2k
        if (tok->st_pos == json_null_str_len)
565
13.3k
        {
566
13.3k
          current = NULL;
567
13.3k
          saved_state = json_tokener_state_finish;
568
13.3k
          state = json_tokener_state_eatws;
569
13.3k
          goto redo_char;
570
13.3k
        }
571
67.2k
      }
572
1.57k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
1.57k
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
99
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
1.47k
      {
576
1.47k
        if (tok->st_pos == json_nan_str_len)
577
486
        {
578
486
          current = json_object_new_double(NAN);
579
486
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
486
          saved_state = json_tokener_state_finish;
585
486
          state = json_tokener_state_eatws;
586
486
          goto redo_char;
587
486
        }
588
1.47k
      }
589
99
      else
590
99
      {
591
99
        tok->err = json_tokener_error_parse_null;
592
99
        goto out;
593
99
      }
594
54.9k
      tok->st_pos++;
595
54.9k
    }
596
0
    break;
597
598
2.53k
    case json_tokener_state_comment_start:
599
2.53k
      if (c == '*')
600
744
      {
601
744
        state = json_tokener_state_comment;
602
744
      }
603
1.79k
      else if (c == '/')
604
1.71k
      {
605
1.71k
        state = json_tokener_state_comment_eol;
606
1.71k
      }
607
78
      else
608
78
      {
609
78
        tok->err = json_tokener_error_parse_comment;
610
78
        goto out;
611
78
      }
612
2.46k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
2.46k
      break;
614
615
3.61k
    case json_tokener_state_comment:
616
3.61k
    {
617
      /* Advance until we change state */
618
3.61k
      const char *case_start = str;
619
431k
      while (c != '*')
620
427k
      {
621
427k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
168
        {
623
168
          printbuf_memappend_checked(tok->pb, case_start,
624
168
                                     str - case_start);
625
168
          goto out;
626
168
        }
627
427k
      }
628
3.44k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
3.44k
      state = json_tokener_state_comment_end;
630
3.44k
    }
631
0
    break;
632
633
1.71k
    case json_tokener_state_comment_eol:
634
1.71k
    {
635
      /* Advance until we change state */
636
1.71k
      const char *case_start = str;
637
223k
      while (c != '\n')
638
222k
      {
639
222k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
123
        {
641
123
          printbuf_memappend_checked(tok->pb, case_start,
642
123
                                     str - case_start);
643
123
          goto out;
644
123
        }
645
222k
      }
646
1.59k
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
1.59k
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
1.59k
      state = json_tokener_state_eatws;
649
1.59k
    }
650
0
    break;
651
652
3.44k
    case json_tokener_state_comment_end:
653
3.44k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
3.44k
      if (c == '/')
655
569
      {
656
569
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
569
        state = json_tokener_state_eatws;
658
569
      }
659
2.87k
      else
660
2.87k
      {
661
2.87k
        state = json_tokener_state_comment;
662
2.87k
      }
663
3.44k
      break;
664
665
118k
    case json_tokener_state_string:
666
118k
    {
667
      /* Advance until we change state */
668
118k
      const char *case_start = str;
669
2.02M
      while (1)
670
2.02M
      {
671
2.02M
        if (c == tok->quote_char)
672
73.5k
        {
673
73.5k
          printbuf_memappend_checked(tok->pb, case_start,
674
73.5k
                                     str - case_start);
675
73.5k
          current =
676
73.5k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
73.5k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
73.5k
          saved_state = json_tokener_state_finish;
683
73.5k
          state = json_tokener_state_eatws;
684
73.5k
          break;
685
73.5k
        }
686
1.95M
        else if (c == '\\')
687
44.9k
        {
688
44.9k
          printbuf_memappend_checked(tok->pb, case_start,
689
44.9k
                                     str - case_start);
690
44.9k
          saved_state = json_tokener_state_string;
691
44.9k
          state = json_tokener_state_string_escape;
692
44.9k
          break;
693
44.9k
        }
694
1.91M
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
695
0
        {
696
          // Disallow control characters in strict mode
697
0
          tok->err = json_tokener_error_parse_string;
698
0
          goto out;
699
0
        }
700
1.91M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
223
        {
702
223
          printbuf_memappend_checked(tok->pb, case_start,
703
223
                                     str - case_start);
704
223
          goto out;
705
223
        }
706
1.91M
      }
707
118k
    }
708
118k
    break;
709
710
118k
    case json_tokener_state_string_escape:
711
57.0k
      switch (c)
712
57.0k
      {
713
10.2k
      case '"':
714
31.2k
      case '\\':
715
31.6k
      case '/':
716
31.6k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
31.6k
        state = saved_state;
718
31.6k
        break;
719
1.11k
      case 'b':
720
18.7k
      case 'n':
721
19.3k
      case 'r':
722
20.3k
      case 't':
723
20.7k
      case 'f':
724
20.7k
        if (c == 'b')
725
1.11k
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
19.6k
        else if (c == 'n')
727
17.6k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
2.01k
        else if (c == 'r')
729
579
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
1.43k
        else if (c == 't')
731
976
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
460
        else if (c == 'f')
733
460
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
20.7k
        state = saved_state;
735
20.7k
        break;
736
4.64k
      case 'u':
737
4.64k
        tok->ucs_char = 0;
738
4.64k
        tok->st_pos = 0;
739
4.64k
        state = json_tokener_state_escape_unicode;
740
4.64k
        break;
741
35
      default: tok->err = json_tokener_error_parse_string; goto out;
742
57.0k
      }
743
57.0k
      break;
744
745
      // ===================================================
746
747
57.0k
    case json_tokener_state_escape_unicode:
748
5.85k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
23.2k
      while (1)
751
23.2k
      {
752
23.2k
        if (!c || !is_hex_char(c))
753
74
        {
754
74
          tok->err = json_tokener_error_parse_string;
755
74
          goto out;
756
74
        }
757
23.1k
        tok->ucs_char |=
758
23.1k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
23.1k
        tok->st_pos++;
760
23.1k
        if (tok->st_pos >= 4)
761
5.77k
          break;
762
763
17.4k
        (void)ADVANCE_CHAR(str, tok);
764
17.4k
        if (!PEEK_CHAR(c, tok))
765
0
        {
766
          /*
767
           * We're out of characters in the current call to
768
           * json_tokener_parse(), but a subsequent call might
769
           * provide us with more, so leave our current state
770
           * as-is (including tok->high_surrogate) and return.
771
           */
772
0
          goto out;
773
0
        }
774
17.4k
      }
775
5.77k
      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
5.77k
      if (tok->high_surrogate)
781
1.19k
      {
782
1.19k
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
643
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
643
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
643
                                                tok->ucs_char);
787
643
        }
788
549
        else
789
549
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
549
          printbuf_memappend_checked(tok->pb,
794
549
                                     (char *)utf8_replacement_char, 3);
795
549
        }
796
1.19k
        tok->high_surrogate = 0;
797
1.19k
      }
798
799
5.77k
      if (tok->ucs_char < 0x80)
800
1.12k
      {
801
1.12k
        unsigned char unescaped_utf[1];
802
1.12k
        unescaped_utf[0] = tok->ucs_char;
803
1.12k
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
1.12k
      }
805
4.65k
      else if (tok->ucs_char < 0x800)
806
366
      {
807
366
        unsigned char unescaped_utf[2];
808
366
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
366
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
366
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
366
      }
812
4.28k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
1.97k
      {
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.97k
        tok->high_surrogate = tok->ucs_char;
829
1.97k
        tok->ucs_char = 0;
830
1.97k
        state = json_tokener_state_escape_unicode_need_escape;
831
1.97k
        break;
832
1.97k
      }
833
2.31k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
856
      {
835
        /* Got a low surrogate not preceded by a high */
836
856
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
856
      }
838
1.46k
      else if (tok->ucs_char < 0x10000)
839
820
      {
840
820
        unsigned char unescaped_utf[3];
841
820
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
820
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
820
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
820
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
820
      }
846
643
      else if (tok->ucs_char < 0x110000)
847
643
      {
848
643
        unsigned char unescaped_utf[4];
849
643
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
643
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
643
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
643
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
643
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
643
      }
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
3.80k
      state = saved_state; // i.e. _state_string or _state_object_field
861
3.80k
    }
862
0
    break;
863
864
1.97k
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
1.97k
      if (!c || c != '\\')
868
442
      {
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
442
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
442
        tok->high_surrogate = 0;
875
442
        tok->ucs_char = 0;
876
442
        tok->st_pos = 0;
877
442
        state = saved_state;
878
442
        goto redo_char;
879
442
      }
880
1.52k
      state = json_tokener_state_escape_unicode_need_u;
881
1.52k
      break;
882
883
1.52k
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
1.52k
      if (!c || c != 'u')
886
324
      {
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
324
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
324
        tok->high_surrogate = 0;
894
324
        tok->ucs_char = 0;
895
324
        tok->st_pos = 0;
896
324
        state = json_tokener_state_string_escape;
897
324
        goto redo_char;
898
324
      }
899
1.20k
      state = json_tokener_state_escape_unicode;
900
1.20k
      break;
901
902
      // ===================================================
903
904
9.58k
    case json_tokener_state_boolean:
905
9.58k
    {
906
9.58k
      int size1, size2;
907
9.58k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
9.58k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
9.58k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
9.58k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
9.58k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
4.20k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
5.38k
      {
914
5.38k
        if (tok->st_pos == json_true_str_len)
915
1.05k
        {
916
1.05k
          current = json_object_new_boolean(1);
917
1.05k
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
1.05k
          saved_state = json_tokener_state_finish;
923
1.05k
          state = json_tokener_state_eatws;
924
1.05k
          goto redo_char;
925
1.05k
        }
926
5.38k
      }
927
4.20k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
4.20k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
148
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
4.06k
      {
931
4.06k
        if (tok->st_pos == json_false_str_len)
932
653
        {
933
653
          current = json_object_new_boolean(0);
934
653
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
653
          saved_state = json_tokener_state_finish;
940
653
          state = json_tokener_state_eatws;
941
653
          goto redo_char;
942
653
        }
943
4.06k
      }
944
148
      else
945
148
      {
946
148
        tok->err = json_tokener_error_parse_boolean;
947
148
        goto out;
948
148
      }
949
7.73k
      tok->st_pos++;
950
7.73k
    }
951
0
    break;
952
953
159k
    case json_tokener_state_number:
954
159k
    {
955
      /* Advance until we change state */
956
159k
      const char *case_start = str;
957
159k
      int case_len = 0;
958
159k
      int is_exponent = 0;
959
159k
      int neg_sign_ok = 1;
960
159k
      int pos_sign_ok = 0;
961
159k
      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
444k
      while (c && ((c >= '0' && c <= '9') ||
986
168k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
165k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
160k
                   (!tok->is_double && c == '.')))
989
285k
      {
990
285k
        pos_sign_ok = neg_sign_ok = 0;
991
285k
        ++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
285k
        switch (c)
1000
285k
        {
1001
1.04k
        case '.':
1002
1.04k
          tok->is_double = 1;
1003
1.04k
          pos_sign_ok = 1;
1004
1.04k
          neg_sign_ok = 1;
1005
1.04k
          break;
1006
2.09k
        case 'e': /* FALLTHRU */
1007
3.18k
        case 'E':
1008
3.18k
          is_exponent = 1;
1009
3.18k
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
3.18k
          pos_sign_ok = neg_sign_ok = 1;
1012
3.18k
          break;
1013
281k
        default: break;
1014
285k
        }
1015
1016
285k
        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
285k
      }
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
159k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
3.25k
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
221
      {
1033
221
        tok->err = json_tokener_error_parse_number;
1034
221
        goto out;
1035
221
      }
1036
159k
      if (case_len > 0)
1037
159k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
159k
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1041
429
      {
1042
429
        state = json_tokener_state_inf;
1043
429
        tok->st_pos = 0;
1044
429
        goto redo_char;
1045
429
      }
1046
158k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
3.68k
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
7.85k
        while (printbuf_length(tok->pb) > 1)
1051
6.09k
        {
1052
6.09k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
6.09k
          if (last_char != 'e' && last_char != 'E' &&
1054
3.69k
              last_char != '-' && last_char != '+')
1055
1.91k
          {
1056
1.91k
            break;
1057
1.91k
          }
1058
4.17k
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
4.17k
          printbuf_length(tok->pb)--;
1060
4.17k
        }
1061
3.68k
      }
1062
158k
    }
1063
0
      {
1064
158k
        int64_t num64;
1065
158k
        uint64_t numuint64;
1066
158k
        double numd;
1067
158k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
2.50k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
2.47k
        {
1070
2.47k
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1071
0
          {
1072
0
            tok->err = json_tokener_error_parse_number;
1073
0
            goto out;
1074
0
          }
1075
2.47k
          current = json_object_new_int64(num64);
1076
2.47k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
2.47k
        }
1082
156k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
152k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
152k
        {
1085
152k
          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
152k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
3.28k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
152k
          if (numuint64 <= INT64_MAX)
1097
151k
          {
1098
151k
            num64 = (uint64_t)numuint64;
1099
151k
            current = json_object_new_int64(num64);
1100
151k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
151k
          }
1106
709
          else
1107
709
          {
1108
709
            current = json_object_new_uint64(numuint64);
1109
709
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
709
          }
1115
152k
        }
1116
3.70k
        else if (tok->is_double &&
1117
3.68k
                 json_tokener_parse_double(
1118
3.68k
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
3.65k
        {
1120
3.65k
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
3.65k
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
3.65k
        }
1127
50
        else
1128
50
        {
1129
50
          tok->err = json_tokener_error_parse_number;
1130
50
          goto out;
1131
50
        }
1132
158k
        saved_state = json_tokener_state_finish;
1133
158k
        state = json_tokener_state_eatws;
1134
158k
        goto redo_char;
1135
158k
      }
1136
0
      break;
1137
1138
173k
    case json_tokener_state_array_after_sep:
1139
188k
    case json_tokener_state_array:
1140
188k
      if (c == ']')
1141
1.93k
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
1.93k
        json_object_array_shrink(current, 0);
1144
1145
1.93k
        if (state == json_tokener_state_array_after_sep &&
1146
619
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
1.93k
        saved_state = json_tokener_state_finish;
1152
1.93k
        state = json_tokener_state_eatws;
1153
1.93k
      }
1154
186k
      else
1155
186k
      {
1156
186k
        if (tok->depth >= tok->max_depth - 1)
1157
6
        {
1158
6
          tok->err = json_tokener_error_depth;
1159
6
          goto out;
1160
6
        }
1161
186k
        state = json_tokener_state_array_add;
1162
186k
        tok->depth++;
1163
186k
        json_tokener_reset_level(tok, tok->depth);
1164
186k
        goto redo_char;
1165
186k
      }
1166
1.93k
      break;
1167
1168
184k
    case json_tokener_state_array_add:
1169
184k
      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
184k
      saved_state = json_tokener_state_array_sep;
1175
184k
      state = json_tokener_state_eatws;
1176
184k
      goto redo_char;
1177
1178
184k
    case json_tokener_state_array_sep:
1179
184k
      if (c == ']')
1180
10.3k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
10.3k
        json_object_array_shrink(current, 0);
1183
1184
10.3k
        saved_state = json_tokener_state_finish;
1185
10.3k
        state = json_tokener_state_eatws;
1186
10.3k
      }
1187
173k
      else if (c == ',')
1188
173k
      {
1189
173k
        saved_state = json_tokener_state_array_after_sep;
1190
173k
        state = json_tokener_state_eatws;
1191
173k
      }
1192
150
      else
1193
150
      {
1194
150
        tok->err = json_tokener_error_parse_array;
1195
150
        goto out;
1196
150
      }
1197
184k
      break;
1198
1199
184k
    case json_tokener_state_object_field_start:
1200
142k
    case json_tokener_state_object_field_start_after_sep:
1201
142k
      if (c == '}')
1202
19.3k
      {
1203
19.3k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
200
            (tok->flags & JSON_TOKENER_STRICT))
1205
0
        {
1206
0
          tok->err = json_tokener_error_parse_unexpected;
1207
0
          goto out;
1208
0
        }
1209
19.3k
        saved_state = json_tokener_state_finish;
1210
19.3k
        state = json_tokener_state_eatws;
1211
19.3k
      }
1212
122k
      else if (c == '"' || c == '\'')
1213
122k
      {
1214
122k
        tok->quote_char = c;
1215
122k
        printbuf_reset(tok->pb);
1216
122k
        state = json_tokener_state_object_field;
1217
122k
      }
1218
70
      else
1219
70
      {
1220
70
        tok->err = json_tokener_error_parse_object_key_name;
1221
70
        goto out;
1222
70
      }
1223
142k
      break;
1224
1225
142k
    case json_tokener_state_object_field:
1226
134k
    {
1227
      /* Advance until we change state */
1228
134k
      const char *case_start = str;
1229
2.02M
      while (1)
1230
2.02M
      {
1231
2.02M
        if (c == tok->quote_char)
1232
122k
        {
1233
122k
          printbuf_memappend_checked(tok->pb, case_start,
1234
122k
                                     str - case_start);
1235
122k
          obj_field_name = strdup(tok->pb->buf);
1236
122k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
122k
          saved_state = json_tokener_state_object_field_end;
1242
122k
          state = json_tokener_state_eatws;
1243
122k
          break;
1244
122k
        }
1245
1.89M
        else if (c == '\\')
1246
11.8k
        {
1247
11.8k
          printbuf_memappend_checked(tok->pb, case_start,
1248
11.8k
                                     str - case_start);
1249
11.8k
          saved_state = json_tokener_state_object_field;
1250
11.8k
          state = json_tokener_state_string_escape;
1251
11.8k
          break;
1252
11.8k
        }
1253
1.88M
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
1254
0
        {
1255
          // Disallow control characters in strict mode
1256
0
          tok->err = json_tokener_error_parse_string;
1257
0
          goto out;
1258
0
        }
1259
1.88M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
184
        {
1261
184
          printbuf_memappend_checked(tok->pb, case_start,
1262
184
                                     str - case_start);
1263
184
          goto out;
1264
184
        }
1265
1.88M
      }
1266
134k
    }
1267
134k
    break;
1268
1269
134k
    case json_tokener_state_object_field_end:
1270
122k
      if (c == ':')
1271
122k
      {
1272
122k
        saved_state = json_tokener_state_object_value;
1273
122k
        state = json_tokener_state_eatws;
1274
122k
      }
1275
139
      else
1276
139
      {
1277
139
        tok->err = json_tokener_error_parse_object_key_sep;
1278
139
        goto out;
1279
139
      }
1280
122k
      break;
1281
1282
122k
    case json_tokener_state_object_value:
1283
122k
      if (tok->depth >= tok->max_depth - 1)
1284
3
      {
1285
3
        tok->err = json_tokener_error_depth;
1286
3
        goto out;
1287
3
      }
1288
122k
      state = json_tokener_state_object_value_add;
1289
122k
      tok->depth++;
1290
122k
      json_tokener_reset_level(tok, tok->depth);
1291
122k
      goto redo_char;
1292
1293
120k
    case json_tokener_state_object_value_add:
1294
120k
      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
120k
      free(obj_field_name);
1300
120k
      obj_field_name = NULL;
1301
120k
      saved_state = json_tokener_state_object_sep;
1302
120k
      state = json_tokener_state_eatws;
1303
120k
      goto redo_char;
1304
1305
120k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
120k
      if (c == '}')
1308
31.9k
      {
1309
31.9k
        saved_state = json_tokener_state_finish;
1310
31.9k
        state = json_tokener_state_eatws;
1311
31.9k
      }
1312
88.3k
      else if (c == ',')
1313
88.0k
      {
1314
88.0k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
88.0k
        state = json_tokener_state_eatws;
1316
88.0k
      }
1317
263
      else
1318
263
      {
1319
263
        tok->err = json_tokener_error_parse_object_value_sep;
1320
263
        goto out;
1321
263
      }
1322
120k
      break;
1323
3.89M
    }
1324
1.10M
    (void)ADVANCE_CHAR(str, tok);
1325
1.10M
    if (!c) // This is the char *before* advancing
1326
7
      break;
1327
1.10M
  } /* while(PEEK_CHAR) */
1328
1329
9.78k
out:
1330
9.78k
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1331
0
  {
1332
0
    tok->err = json_tokener_error_parse_utf8_string;
1333
0
  }
1334
9.78k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
98
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
98
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
9.78k
  if (!c)
1342
8.22k
  {
1343
    /* We hit an eof char (0) */
1344
8.22k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
728
      tok->err = json_tokener_error_parse_eof;
1346
8.22k
  }
1347
1348
9.78k
#ifdef HAVE_USELOCALE
1349
9.78k
  uselocale(oldlocale);
1350
9.78k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
9.78k
  if (tok->err == json_tokener_success)
1357
7.59k
  {
1358
7.59k
    json_object *ret = json_object_get(current);
1359
7.59k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
15.5k
    for (ii = tok->depth; ii >= 0; ii--)
1363
7.99k
      json_tokener_reset_level(tok, ii);
1364
7.59k
    return ret;
1365
7.59k
  }
1366
1367
2.18k
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
2.18k
           tok->char_offset);
1369
2.18k
  return NULL;
1370
9.78k
}
1371
1372
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes)
1373
0
{
1374
0
  unsigned char chr = c;
1375
0
  if (*nBytes == 0)
1376
0
  {
1377
0
    if (chr >= 0x80)
1378
0
    {
1379
0
      if ((chr & 0xe0) == 0xc0)
1380
0
        *nBytes = 1;
1381
0
      else if ((chr & 0xf0) == 0xe0)
1382
0
        *nBytes = 2;
1383
0
      else if ((chr & 0xf8) == 0xf0)
1384
0
        *nBytes = 3;
1385
0
      else
1386
0
        return 0;
1387
0
    }
1388
0
  }
1389
0
  else
1390
0
  {
1391
0
    if ((chr & 0xC0) != 0x80)
1392
0
      return 0;
1393
0
    (*nBytes)--;
1394
0
  }
1395
0
  return 1;
1396
0
}
1397
1398
void json_tokener_set_flags(struct json_tokener *tok, int flags)
1399
0
{
1400
0
  tok->flags = flags;
1401
0
}
1402
1403
size_t json_tokener_get_parse_end(struct json_tokener *tok)
1404
0
{
1405
0
  assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */
1406
0
  return (size_t)tok->char_offset;
1407
0
}
1408
1409
static int json_tokener_parse_double(const char *buf, int len, double *retval)
1410
3.68k
{
1411
3.68k
  char *end;
1412
3.68k
  *retval = strtod(buf, &end);
1413
3.68k
  if (buf + len == end)
1414
3.65k
    return 0; // It worked
1415
26
  return 1;
1416
3.68k
}