Coverage Report

Created: 2026-03-09 06:12

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
22.8k
#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.64M
{
71
1.64M
  return c == ' '
72
1.49M
      || c == '\t'
73
1.47M
      || c == '\n'
74
1.47M
      || c == '\r';
75
1.64M
}
76
77
static inline int is_hex_char(char c)
78
22.8k
{
79
22.8k
  return (c >= '0' && c <= '9')
80
9.55k
      || (c >= 'A' && c <= 'F')
81
1.85k
      || (c >= 'a' && c <= 'f');
82
22.8k
}
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.01k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
3.25k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
564
#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.32k
{
155
9.32k
  struct json_tokener *tok;
156
157
9.32k
  if (depth < 1)
158
0
    return NULL;
159
160
9.32k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
9.32k
  if (!tok)
162
0
    return NULL;
163
9.32k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
9.32k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
9.32k
  tok->pb = printbuf_new();
170
9.32k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
9.32k
  tok->max_depth = depth;
177
9.32k
  json_tokener_reset(tok);
178
9.32k
  return tok;
179
9.32k
}
180
181
struct json_tokener *json_tokener_new(void)
182
9.32k
{
183
9.32k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
9.32k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
9.32k
{
188
9.32k
  if (!tok)
189
0
    return;
190
9.32k
  json_tokener_reset(tok);
191
9.32k
  if (tok->pb)
192
9.32k
    printbuf_free(tok->pb);
193
9.32k
  free(tok->stack);
194
9.32k
  free(tok);
195
9.32k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
625k
{
199
625k
  tok->stack[depth].state = json_tokener_state_eatws;
200
625k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
625k
  json_object_put(tok->stack[depth].current);
202
625k
  tok->stack[depth].current = NULL;
203
625k
  free(tok->stack[depth].obj_field_name);
204
625k
  tok->stack[depth].obj_field_name = NULL;
205
625k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
18.6k
{
209
18.6k
  int i;
210
18.6k
  if (!tok)
211
0
    return;
212
213
41.1k
  for (i = tok->depth; i >= 0; i--)
214
22.4k
    json_tokener_reset_level(tok, i);
215
18.6k
  tok->depth = 0;
216
18.6k
  tok->err = json_tokener_success;
217
18.6k
}
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.24M
#define state tok->stack[tok->depth].state
262
2.73M
#define saved_state tok->stack[tok->depth].saved_state
263
1.21M
#define current tok->stack[tok->depth].current
264
592k
#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.14M
  (((tok)->char_offset == len)                                         \
286
6.14M
       ? (((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.14M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
6.14M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
6.14M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
6.14M
              : (((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.9M
#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
552k
  do {                                                  \
308
552k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
552k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
552k
  } 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.32k
{
319
9.32k
  struct json_object *obj = NULL;
320
9.32k
  char c = '\1';
321
9.32k
  unsigned int nBytes = 0;
322
9.32k
  unsigned int *nBytesp = &nBytes;
323
324
9.32k
#ifdef HAVE_USELOCALE
325
9.32k
  locale_t oldlocale = uselocale(NULL);
326
9.32k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
9.32k
  tok->char_offset = 0;
332
9.32k
  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.32k
  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.32k
#ifdef HAVE_USELOCALE
347
9.32k
  {
348
9.32k
#ifdef HAVE_DUPLOCALE
349
9.32k
    locale_t duploc = duplocale(oldlocale);
350
9.32k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
9.32k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
9.32k
    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.32k
    uselocale(newloc);
375
9.32k
  }
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.08M
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
1.08M
  {
395
396
3.79M
  redo_char:
397
3.79M
    switch (state)
398
3.79M
    {
399
400
1.47M
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
1.63M
      while (is_ws_char(c))
403
168k
      {
404
168k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
168k
      }
407
1.47M
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
2.45k
      {
409
2.45k
        printbuf_reset(tok->pb);
410
2.45k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
2.45k
        state = json_tokener_state_comment_start;
412
2.45k
      }
413
1.46M
      else
414
1.46M
      {
415
1.46M
        state = saved_state;
416
1.46M
        goto redo_char;
417
1.46M
      }
418
2.45k
      break;
419
420
309k
    case json_tokener_state_start:
421
309k
      switch (c)
422
309k
      {
423
51.8k
      case '{':
424
51.8k
        state = json_tokener_state_eatws;
425
51.8k
        saved_state = json_tokener_state_object_field_start;
426
51.8k
        current = json_object_new_object();
427
51.8k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
51.8k
        break;
433
51.8k
      case '[':
434
14.2k
        state = json_tokener_state_eatws;
435
14.2k
        saved_state = json_tokener_state_array;
436
14.2k
        current = json_object_new_array();
437
14.2k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
14.2k
        break;
443
14.2k
      case 'I':
444
614
      case 'i':
445
614
        state = json_tokener_state_inf;
446
614
        printbuf_reset(tok->pb);
447
614
        tok->st_pos = 0;
448
614
        goto redo_char;
449
1.02k
      case 'N':
450
14.2k
      case 'n':
451
14.2k
        state = json_tokener_state_null; // or NaN
452
14.2k
        printbuf_reset(tok->pb);
453
14.2k
        tok->st_pos = 0;
454
14.2k
        goto redo_char;
455
507
      case '\'':
456
507
        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
70.5k
      case '"':
464
70.5k
        state = json_tokener_state_string;
465
70.5k
        printbuf_reset(tok->pb);
466
70.5k
        tok->quote_char = c;
467
70.5k
        break;
468
605
      case 'T':
469
1.13k
      case 't':
470
1.27k
      case 'F':
471
1.88k
      case 'f':
472
1.88k
        state = json_tokener_state_boolean;
473
1.88k
        printbuf_reset(tok->pb);
474
1.88k
        tok->st_pos = 0;
475
1.88k
        goto redo_char;
476
20.1k
      case '0':
477
27.2k
      case '1':
478
31.1k
      case '2':
479
33.8k
      case '3':
480
37.0k
      case '4':
481
148k
      case '5':
482
149k
      case '6':
483
150k
      case '7':
484
150k
      case '8':
485
152k
      case '9':
486
155k
      case '-':
487
155k
        state = json_tokener_state_number;
488
155k
        printbuf_reset(tok->pb);
489
155k
        tok->is_double = 0;
490
155k
        goto redo_char;
491
135
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
309k
      }
493
136k
      break;
494
495
303k
    case json_tokener_state_finish:
496
303k
      if (tok->depth == 0)
497
7.05k
        goto out;
498
295k
      obj = json_object_get(current);
499
295k
      json_tokener_reset_level(tok, tok->depth);
500
295k
      tok->depth--;
501
295k
      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.04k
      while (tok->st_pos < (int)json_inf_str_len)
516
8.07k
      {
517
8.07k
        char inf_char = *str;
518
8.07k
        if (inf_char != json_inf_str[tok->st_pos] &&
519
3.54k
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
3.54k
              inf_char != json_inf_str_invert[tok->st_pos])
521
8.07k
           )
522
99
        {
523
99
          tok->err = json_tokener_error_parse_unexpected;
524
99
          goto out;
525
99
        }
526
7.97k
        tok->st_pos++;
527
7.97k
        (void)ADVANCE_CHAR(str, tok);
528
7.97k
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
7.97k
      }
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
972
      if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
539
429
      {
540
429
        is_negative = 1;
541
429
      }
542
972
      current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
543
972
      if (current == NULL)
544
0
      {
545
0
        tok->err = json_tokener_error_memory;
546
0
        goto out;
547
0
      }
548
972
      saved_state = json_tokener_state_finish;
549
972
      state = json_tokener_state_eatws;
550
972
      goto redo_char;
551
972
    }
552
0
    break;
553
70.5k
    case json_tokener_state_null: /* aka starts with 'n' */
554
70.5k
    {
555
70.5k
      int size;
556
70.5k
      int size_nan;
557
70.5k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
70.5k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
70.5k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
70.5k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
70.5k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
1.58k
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
68.9k
      {
564
68.9k
        if (tok->st_pos == json_null_str_len)
565
13.6k
        {
566
13.6k
          current = NULL;
567
13.6k
          saved_state = json_tokener_state_finish;
568
13.6k
          state = json_tokener_state_eatws;
569
13.6k
          goto redo_char;
570
13.6k
        }
571
68.9k
      }
572
1.58k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
1.58k
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
101
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
1.48k
      {
576
1.48k
        if (tok->st_pos == json_nan_str_len)
577
487
        {
578
487
          current = json_object_new_double(NAN);
579
487
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
487
          saved_state = json_tokener_state_finish;
585
487
          state = json_tokener_state_eatws;
586
487
          goto redo_char;
587
487
        }
588
1.48k
      }
589
101
      else
590
101
      {
591
101
        tok->err = json_tokener_error_parse_null;
592
101
        goto out;
593
101
      }
594
56.3k
      tok->st_pos++;
595
56.3k
    }
596
0
    break;
597
598
2.45k
    case json_tokener_state_comment_start:
599
2.45k
      if (c == '*')
600
714
      {
601
714
        state = json_tokener_state_comment;
602
714
      }
603
1.73k
      else if (c == '/')
604
1.66k
      {
605
1.66k
        state = json_tokener_state_comment_eol;
606
1.66k
      }
607
75
      else
608
75
      {
609
75
        tok->err = json_tokener_error_parse_comment;
610
75
        goto out;
611
75
      }
612
2.37k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
2.37k
      break;
614
615
4.17k
    case json_tokener_state_comment:
616
4.17k
    {
617
      /* Advance until we change state */
618
4.17k
      const char *case_start = str;
619
504k
      while (c != '*')
620
500k
      {
621
500k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
169
        {
623
169
          printbuf_memappend_checked(tok->pb, case_start,
624
169
                                     str - case_start);
625
169
          goto out;
626
169
        }
627
500k
      }
628
4.00k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
4.00k
      state = json_tokener_state_comment_end;
630
4.00k
    }
631
0
    break;
632
633
1.66k
    case json_tokener_state_comment_eol:
634
1.66k
    {
635
      /* Advance until we change state */
636
1.66k
      const char *case_start = str;
637
308k
      while (c != '\n')
638
306k
      {
639
306k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
129
        {
641
129
          printbuf_memappend_checked(tok->pb, case_start,
642
129
                                     str - case_start);
643
129
          goto out;
644
129
        }
645
306k
      }
646
1.53k
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
1.53k
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
1.53k
      state = json_tokener_state_eatws;
649
1.53k
    }
650
0
    break;
651
652
4.00k
    case json_tokener_state_comment_end:
653
4.00k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
4.00k
      if (c == '/')
655
536
      {
656
536
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
536
        state = json_tokener_state_eatws;
658
536
      }
659
3.47k
      else
660
3.47k
      {
661
3.47k
        state = json_tokener_state_comment;
662
3.47k
      }
663
4.00k
      break;
664
665
113k
    case json_tokener_state_string:
666
113k
    {
667
      /* Advance until we change state */
668
113k
      const char *case_start = str;
669
1.99M
      while (1)
670
1.99M
      {
671
1.99M
        if (c == tok->quote_char)
672
70.3k
        {
673
70.3k
          printbuf_memappend_checked(tok->pb, case_start,
674
70.3k
                                     str - case_start);
675
70.3k
          current =
676
70.3k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
70.3k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
70.3k
          saved_state = json_tokener_state_finish;
683
70.3k
          state = json_tokener_state_eatws;
684
70.3k
          break;
685
70.3k
        }
686
1.92M
        else if (c == '\\')
687
42.9k
        {
688
42.9k
          printbuf_memappend_checked(tok->pb, case_start,
689
42.9k
                                     str - case_start);
690
42.9k
          saved_state = json_tokener_state_string;
691
42.9k
          state = json_tokener_state_string_escape;
692
42.9k
          break;
693
42.9k
        }
694
1.87M
        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.87M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
230
        {
702
230
          printbuf_memappend_checked(tok->pb, case_start,
703
230
                                     str - case_start);
704
230
          goto out;
705
230
        }
706
1.87M
      }
707
113k
    }
708
113k
    break;
709
710
113k
    case json_tokener_state_string_escape:
711
55.5k
      switch (c)
712
55.5k
      {
713
9.95k
      case '"':
714
30.0k
      case '\\':
715
30.4k
      case '/':
716
30.4k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
30.4k
        state = saved_state;
718
30.4k
        break;
719
1.23k
      case 'b':
720
18.4k
      case 'n':
721
19.0k
      case 'r':
722
20.0k
      case 't':
723
20.4k
      case 'f':
724
20.4k
        if (c == 'b')
725
1.23k
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
19.2k
        else if (c == 'n')
727
17.2k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
2.00k
        else if (c == 'r')
729
580
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
1.42k
        else if (c == 't')
731
970
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
454
        else if (c == 'f')
733
454
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
20.4k
        state = saved_state;
735
20.4k
        break;
736
4.63k
      case 'u':
737
4.63k
        tok->ucs_char = 0;
738
4.63k
        tok->st_pos = 0;
739
4.63k
        state = json_tokener_state_escape_unicode;
740
4.63k
        break;
741
31
      default: tok->err = json_tokener_error_parse_string; goto out;
742
55.5k
      }
743
55.5k
      break;
744
745
      // ===================================================
746
747
55.5k
    case json_tokener_state_escape_unicode:
748
5.75k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
22.8k
      while (1)
751
22.8k
      {
752
22.8k
        if (!c || !is_hex_char(c))
753
72
        {
754
72
          tok->err = json_tokener_error_parse_string;
755
72
          goto out;
756
72
        }
757
22.8k
        tok->ucs_char |=
758
22.8k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
22.8k
        tok->st_pos++;
760
22.8k
        if (tok->st_pos >= 4)
761
5.68k
          break;
762
763
17.1k
        (void)ADVANCE_CHAR(str, tok);
764
17.1k
        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.1k
      }
775
5.68k
      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.68k
      if (tok->high_surrogate)
781
1.10k
      {
782
1.10k
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
564
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
564
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
564
                                                tok->ucs_char);
787
564
        }
788
542
        else
789
542
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
542
          printbuf_memappend_checked(tok->pb,
794
542
                                     (char *)utf8_replacement_char, 3);
795
542
        }
796
1.10k
        tok->high_surrogate = 0;
797
1.10k
      }
798
799
5.68k
      if (tok->ucs_char < 0x80)
800
1.11k
      {
801
1.11k
        unsigned char unescaped_utf[1];
802
1.11k
        unescaped_utf[0] = tok->ucs_char;
803
1.11k
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
1.11k
      }
805
4.56k
      else if (tok->ucs_char < 0x800)
806
550
      {
807
550
        unsigned char unescaped_utf[2];
808
550
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
550
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
550
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
550
      }
812
4.01k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
1.87k
      {
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.87k
        tok->high_surrogate = tok->ucs_char;
829
1.87k
        tok->ucs_char = 0;
830
1.87k
        state = json_tokener_state_escape_unicode_need_escape;
831
1.87k
        break;
832
1.87k
      }
833
2.14k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
808
      {
835
        /* Got a low surrogate not preceded by a high */
836
808
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
808
      }
838
1.33k
      else if (tok->ucs_char < 0x10000)
839
773
      {
840
773
        unsigned char unescaped_utf[3];
841
773
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
773
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
773
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
773
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
773
      }
846
564
      else if (tok->ucs_char < 0x110000)
847
564
      {
848
564
        unsigned char unescaped_utf[4];
849
564
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
564
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
564
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
564
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
564
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
564
      }
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.81k
      state = saved_state; // i.e. _state_string or _state_object_field
861
3.81k
    }
862
0
    break;
863
864
1.87k
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
1.87k
      if (!c || c != '\\')
868
452
      {
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
452
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
452
        tok->high_surrogate = 0;
875
452
        tok->ucs_char = 0;
876
452
        tok->st_pos = 0;
877
452
        state = saved_state;
878
452
        goto redo_char;
879
452
      }
880
1.42k
      state = json_tokener_state_escape_unicode_need_u;
881
1.42k
      break;
882
883
1.42k
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
1.42k
      if (!c || c != 'u')
886
301
      {
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
301
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
301
        tok->high_surrogate = 0;
894
301
        tok->ucs_char = 0;
895
301
        tok->st_pos = 0;
896
301
        state = json_tokener_state_string_escape;
897
301
        goto redo_char;
898
301
      }
899
1.11k
      state = json_tokener_state_escape_unicode;
900
1.11k
      break;
901
902
      // ===================================================
903
904
9.82k
    case json_tokener_state_boolean:
905
9.82k
    {
906
9.82k
      int size1, size2;
907
9.82k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
9.82k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
9.82k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
9.82k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
9.82k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
4.42k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
5.39k
      {
914
5.39k
        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.39k
      }
927
4.42k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
4.42k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
146
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
4.27k
      {
931
4.27k
        if (tok->st_pos == json_false_str_len)
932
689
        {
933
689
          current = json_object_new_boolean(0);
934
689
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
689
          saved_state = json_tokener_state_finish;
940
689
          state = json_tokener_state_eatws;
941
689
          goto redo_char;
942
689
        }
943
4.27k
      }
944
146
      else
945
146
      {
946
146
        tok->err = json_tokener_error_parse_boolean;
947
146
        goto out;
948
146
      }
949
7.93k
      tok->st_pos++;
950
7.93k
    }
951
0
    break;
952
953
155k
    case json_tokener_state_number:
954
155k
    {
955
      /* Advance until we change state */
956
155k
      const char *case_start = str;
957
155k
      int case_len = 0;
958
155k
      int is_exponent = 0;
959
155k
      int neg_sign_ok = 1;
960
155k
      int pos_sign_ok = 0;
961
155k
      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
443k
      while (c && ((c >= '0' && c <= '9') ||
986
164k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
161k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
156k
                   (!tok->is_double && c == '.')))
989
288k
      {
990
288k
        pos_sign_ok = neg_sign_ok = 0;
991
288k
        ++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
288k
        switch (c)
1000
288k
        {
1001
897
        case '.':
1002
897
          tok->is_double = 1;
1003
897
          pos_sign_ok = 1;
1004
897
          neg_sign_ok = 1;
1005
897
          break;
1006
1.60k
        case 'e': /* FALLTHRU */
1007
2.86k
        case 'E':
1008
2.86k
          is_exponent = 1;
1009
2.86k
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
2.86k
          pos_sign_ok = neg_sign_ok = 1;
1012
2.86k
          break;
1013
284k
        default: break;
1014
288k
        }
1015
1016
288k
        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
288k
      }
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
155k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
3.79k
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
220
      {
1033
220
        tok->err = json_tokener_error_parse_number;
1034
220
        goto out;
1035
220
      }
1036
155k
      if (case_len > 0)
1037
155k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
155k
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1041
457
      {
1042
457
        state = json_tokener_state_inf;
1043
457
        tok->st_pos = 0;
1044
457
        goto redo_char;
1045
457
      }
1046
154k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
3.23k
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
6.85k
        while (printbuf_length(tok->pb) > 1)
1051
5.34k
        {
1052
5.34k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
5.34k
          if (last_char != 'e' && last_char != 'E' &&
1054
3.21k
              last_char != '-' && last_char != '+')
1055
1.71k
          {
1056
1.71k
            break;
1057
1.71k
          }
1058
3.62k
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
3.62k
          printbuf_length(tok->pb)--;
1060
3.62k
        }
1061
3.23k
      }
1062
154k
    }
1063
0
      {
1064
154k
        int64_t num64;
1065
154k
        uint64_t numuint64;
1066
154k
        double numd;
1067
154k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
2.44k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
2.42k
        {
1070
2.42k
          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.42k
          current = json_object_new_int64(num64);
1076
2.42k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
2.42k
        }
1082
152k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
149k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
149k
        {
1085
149k
          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
149k
          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
149k
          if (numuint64 <= INT64_MAX)
1097
148k
          {
1098
148k
            num64 = (uint64_t)numuint64;
1099
148k
            current = json_object_new_int64(num64);
1100
148k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
148k
          }
1106
711
          else
1107
711
          {
1108
711
            current = json_object_new_uint64(numuint64);
1109
711
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
711
          }
1115
149k
        }
1116
3.25k
        else if (tok->is_double &&
1117
3.23k
                 json_tokener_parse_double(
1118
3.23k
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
3.20k
        {
1120
3.20k
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
3.20k
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
3.20k
        }
1127
47
        else
1128
47
        {
1129
47
          tok->err = json_tokener_error_parse_number;
1130
47
          goto out;
1131
47
        }
1132
154k
        saved_state = json_tokener_state_finish;
1133
154k
        state = json_tokener_state_eatws;
1134
154k
        goto redo_char;
1135
154k
      }
1136
0
      break;
1137
1138
168k
    case json_tokener_state_array_after_sep:
1139
182k
    case json_tokener_state_array:
1140
182k
      if (c == ']')
1141
1.95k
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
1.95k
        json_object_array_shrink(current, 0);
1144
1145
1.95k
        if (state == json_tokener_state_array_after_sep &&
1146
624
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
1.95k
        saved_state = json_tokener_state_finish;
1152
1.95k
        state = json_tokener_state_eatws;
1153
1.95k
      }
1154
180k
      else
1155
180k
      {
1156
180k
        if (tok->depth >= tok->max_depth - 1)
1157
8
        {
1158
8
          tok->err = json_tokener_error_depth;
1159
8
          goto out;
1160
8
        }
1161
180k
        state = json_tokener_state_array_add;
1162
180k
        tok->depth++;
1163
180k
        json_tokener_reset_level(tok, tok->depth);
1164
180k
        goto redo_char;
1165
180k
      }
1166
1.95k
      break;
1167
1168
178k
    case json_tokener_state_array_add:
1169
178k
      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
178k
      saved_state = json_tokener_state_array_sep;
1175
178k
      state = json_tokener_state_eatws;
1176
178k
      goto redo_char;
1177
1178
178k
    case json_tokener_state_array_sep:
1179
178k
      if (c == ']')
1180
10.0k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
10.0k
        json_object_array_shrink(current, 0);
1183
1184
10.0k
        saved_state = json_tokener_state_finish;
1185
10.0k
        state = json_tokener_state_eatws;
1186
10.0k
      }
1187
168k
      else if (c == ',')
1188
168k
      {
1189
168k
        saved_state = json_tokener_state_array_after_sep;
1190
168k
        state = json_tokener_state_eatws;
1191
168k
      }
1192
144
      else
1193
144
      {
1194
144
        tok->err = json_tokener_error_parse_array;
1195
144
        goto out;
1196
144
      }
1197
178k
      break;
1198
1199
178k
    case json_tokener_state_object_field_start:
1200
138k
    case json_tokener_state_object_field_start_after_sep:
1201
138k
      if (c == '}')
1202
18.4k
      {
1203
18.4k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
199
            (tok->flags & JSON_TOKENER_STRICT))
1205
0
        {
1206
0
          tok->err = json_tokener_error_parse_unexpected;
1207
0
          goto out;
1208
0
        }
1209
18.4k
        saved_state = json_tokener_state_finish;
1210
18.4k
        state = json_tokener_state_eatws;
1211
18.4k
      }
1212
120k
      else if (c == '"' || c == '\'')
1213
120k
      {
1214
120k
        tok->quote_char = c;
1215
120k
        printbuf_reset(tok->pb);
1216
120k
        state = json_tokener_state_object_field;
1217
120k
      }
1218
84
      else
1219
84
      {
1220
84
        tok->err = json_tokener_error_parse_object_key_name;
1221
84
        goto out;
1222
84
      }
1223
138k
      break;
1224
1225
138k
    case json_tokener_state_object_field:
1226
132k
    {
1227
      /* Advance until we change state */
1228
132k
      const char *case_start = str;
1229
2.02M
      while (1)
1230
2.02M
      {
1231
2.02M
        if (c == tok->quote_char)
1232
119k
        {
1233
119k
          printbuf_memappend_checked(tok->pb, case_start,
1234
119k
                                     str - case_start);
1235
119k
          obj_field_name = strdup(tok->pb->buf);
1236
119k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
119k
          saved_state = json_tokener_state_object_field_end;
1242
119k
          state = json_tokener_state_eatws;
1243
119k
          break;
1244
119k
        }
1245
1.90M
        else if (c == '\\')
1246
12.2k
        {
1247
12.2k
          printbuf_memappend_checked(tok->pb, case_start,
1248
12.2k
                                     str - case_start);
1249
12.2k
          saved_state = json_tokener_state_object_field;
1250
12.2k
          state = json_tokener_state_string_escape;
1251
12.2k
          break;
1252
12.2k
        }
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
179
        {
1261
179
          printbuf_memappend_checked(tok->pb, case_start,
1262
179
                                     str - case_start);
1263
179
          goto out;
1264
179
        }
1265
1.88M
      }
1266
132k
    }
1267
132k
    break;
1268
1269
132k
    case json_tokener_state_object_field_end:
1270
119k
      if (c == ':')
1271
119k
      {
1272
119k
        saved_state = json_tokener_state_object_value;
1273
119k
        state = json_tokener_state_eatws;
1274
119k
      }
1275
140
      else
1276
140
      {
1277
140
        tok->err = json_tokener_error_parse_object_key_sep;
1278
140
        goto out;
1279
140
      }
1280
119k
      break;
1281
1282
119k
    case json_tokener_state_object_value:
1283
119k
      if (tok->depth >= tok->max_depth - 1)
1284
3
      {
1285
3
        tok->err = json_tokener_error_depth;
1286
3
        goto out;
1287
3
      }
1288
119k
      state = json_tokener_state_object_value_add;
1289
119k
      tok->depth++;
1290
119k
      json_tokener_reset_level(tok, tok->depth);
1291
119k
      goto redo_char;
1292
1293
117k
    case json_tokener_state_object_value_add:
1294
117k
      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
117k
      free(obj_field_name);
1300
117k
      obj_field_name = NULL;
1301
117k
      saved_state = json_tokener_state_object_sep;
1302
117k
      state = json_tokener_state_eatws;
1303
117k
      goto redo_char;
1304
1305
117k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
117k
      if (c == '}')
1308
30.6k
      {
1309
30.6k
        saved_state = json_tokener_state_finish;
1310
30.6k
        state = json_tokener_state_eatws;
1311
30.6k
      }
1312
87.0k
      else if (c == ',')
1313
86.7k
      {
1314
86.7k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
86.7k
        state = json_tokener_state_eatws;
1316
86.7k
      }
1317
256
      else
1318
256
      {
1319
256
        tok->err = json_tokener_error_parse_object_value_sep;
1320
256
        goto out;
1321
256
      }
1322
117k
      break;
1323
3.79M
    }
1324
1.07M
    (void)ADVANCE_CHAR(str, tok);
1325
1.07M
    if (!c) // This is the char *before* advancing
1326
9
      break;
1327
1.07M
  } /* while(PEEK_CHAR) */
1328
1329
9.32k
out:
1330
9.32k
  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.32k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
104
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
104
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
9.32k
  if (!c)
1342
7.77k
  {
1343
    /* We hit an eof char (0) */
1344
7.77k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
738
      tok->err = json_tokener_error_parse_eof;
1346
7.77k
  }
1347
1348
9.32k
#ifdef HAVE_USELOCALE
1349
9.32k
  uselocale(oldlocale);
1350
9.32k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
9.32k
  if (tok->err == json_tokener_success)
1357
7.14k
  {
1358
7.14k
    json_object *ret = json_object_get(current);
1359
7.14k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
14.6k
    for (ii = tok->depth; ii >= 0; ii--)
1363
7.49k
      json_tokener_reset_level(tok, ii);
1364
7.14k
    return ret;
1365
7.14k
  }
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.32k
}
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.23k
{
1411
3.23k
  char *end;
1412
3.23k
  *retval = strtod(buf, &end);
1413
3.23k
  if (buf + len == end)
1414
3.20k
    return 0; // It worked
1415
27
  return 1;
1416
3.23k
}