Coverage Report

Created: 2025-12-14 06:35

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