Coverage Report

Created: 2026-07-24 06:26

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
10.7k
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9)
48
49
#if !HAVE_STRNCASECMP && defined(_WIN32)
50
/* MSC has the version as _strnicmp */
51
#define strncasecmp _strnicmp
52
#elif !HAVE_STRNCASECMP
53
#error You do not have strncasecmp on your system.
54
#endif /* HAVE_STRNCASECMP */
55
56
#if defined(_MSC_VER) && (_MSC_VER <= 1800)
57
/* VS2013 doesn't know about "inline" */
58
#define inline __inline
59
#elif defined(AIX_CC)
60
#define inline
61
#endif
62
63
/* The following helper functions are used to speed up parsing. They
64
 * are faster than their ctype counterparts because they assume that
65
 * the input is in ASCII and that the locale is set to "C". The
66
 * compiler will also inline these functions, providing an additional
67
 * speedup by saving on function calls.
68
 */
69
static inline int is_ws_char(char c)
70
1.02M
{
71
1.02M
  return c == ' '
72
833k
      || c == '\t'
73
803k
      || c == '\n'
74
800k
      || c == '\r';
75
1.02M
}
76
77
static inline int is_hex_char(char c)
78
10.7k
{
79
10.7k
  return (c >= '0' && c <= '9')
80
3.49k
      || (c >= 'A' && c <= 'F')
81
228
      || (c >= 'a' && c <= 'f');
82
10.7k
}
83
84
/* Use C99 NAN by default; if not available, nan("") should work too. */
85
#ifndef NAN
86
#define NAN nan("")
87
#endif /* !NAN */
88
89
static const char json_null_str[] = "null";
90
static const int json_null_str_len = sizeof(json_null_str) - 1;
91
static const char json_inf_str[] = "Infinity";
92
/* Swapped case "Infinity" to avoid need to call tolower() on input chars: */
93
static const char json_inf_str_invert[] = "iNFINITY";
94
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
95
static const char json_nan_str[] = "NaN";
96
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
97
static const char json_true_str[] = "true";
98
static const int json_true_str_len = sizeof(json_true_str) - 1;
99
static const char json_false_str[] = "false";
100
static const int json_false_str_len = sizeof(json_false_str) - 1;
101
102
/* clang-format off */
103
static const char *json_tokener_errors[] = {
104
  "success",
105
  "continue",
106
  "nesting too deep",
107
  "unexpected end of data",
108
  "unexpected character",
109
  "null expected",
110
  "boolean expected",
111
  "number expected",
112
  "array value separator ',' expected",
113
  "quoted object property name expected",
114
  "object property name separator ':' expected",
115
  "object value separator ',' expected",
116
  "invalid string sequence",
117
  "expected comment",
118
  "invalid utf-8 string",
119
  "buffer size overflow",
120
  "out of memory"
121
};
122
/* clang-format on */
123
124
/**
125
 * validete the utf-8 string in strict model.
126
 * if not utf-8 format, return err.
127
 */
128
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes);
129
130
static int json_tokener_parse_double(const char *buf, int len, double *retval);
131
132
const char *json_tokener_error_desc(enum json_tokener_error jerr)
133
408
{
134
408
  int jerr_int = (int)jerr;
135
408
  if (jerr_int < 0 ||
136
408
      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
408
  return json_tokener_errors[jerr];
140
408
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
816
{
144
816
  return tok->err;
145
816
}
146
147
/* Stuff for decoding unicode sequences */
148
1.75k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.49k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
290
#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.55k
{
155
6.55k
  struct json_tokener *tok;
156
157
6.55k
  if (depth < 1)
158
0
    return NULL;
159
160
6.55k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
6.55k
  if (!tok)
162
0
    return NULL;
163
6.55k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
6.55k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
6.55k
  tok->pb = printbuf_new();
170
6.55k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
6.55k
  tok->max_depth = depth;
177
6.55k
  json_tokener_reset(tok);
178
6.55k
  return tok;
179
6.55k
}
180
181
struct json_tokener *json_tokener_new(void)
182
6.55k
{
183
6.55k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
6.55k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
6.55k
{
188
6.55k
  if (!tok)
189
0
    return;
190
6.55k
  json_tokener_reset(tok);
191
6.55k
  if (tok->pb)
192
6.55k
    printbuf_free(tok->pb);
193
6.55k
  free(tok->stack);
194
6.55k
  free(tok);
195
6.55k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
296k
{
199
296k
  tok->stack[depth].state = json_tokener_state_eatws;
200
296k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
296k
  json_object_put(tok->stack[depth].current);
202
296k
  tok->stack[depth].current = NULL;
203
296k
  free(tok->stack[depth].obj_field_name);
204
296k
  tok->stack[depth].obj_field_name = NULL;
205
296k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
13.1k
{
209
13.1k
  int i;
210
13.1k
  if (!tok)
211
0
    return;
212
213
27.2k
  for (i = tok->depth; i >= 0; i--)
214
14.1k
    json_tokener_reset_level(tok, i);
215
13.1k
  tok->depth = 0;
216
13.1k
  tok->err = json_tokener_success;
217
13.1k
}
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.97M
#define state tok->stack[tok->depth].state
262
1.55M
#define saved_state tok->stack[tok->depth].saved_state
263
580k
#define current tok->stack[tok->depth].current
264
535k
#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.61M
  (((tok)->char_offset == len)                                         \
286
3.61M
       ? (((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.61M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.61M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.61M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.61M
              : (((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
6.17M
#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
306k
  do {                                                  \
308
306k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
306k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
306k
  } 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.55k
{
319
6.55k
  struct json_object *obj = NULL;
320
6.55k
  char c = '\1';
321
6.55k
  unsigned int nBytes = 0;
322
6.55k
  unsigned int *nBytesp = &nBytes;
323
324
6.55k
#ifdef HAVE_USELOCALE
325
6.55k
  locale_t oldlocale = uselocale(NULL);
326
6.55k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
6.55k
  tok->char_offset = 0;
332
6.55k
  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.55k
  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.55k
#ifdef HAVE_USELOCALE
347
6.55k
  {
348
6.55k
#ifdef HAVE_DUPLOCALE
349
6.55k
    locale_t duploc = duplocale(oldlocale);
350
6.55k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
6.55k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
6.55k
    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.55k
    uselocale(newloc);
375
6.55k
  }
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
807k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
807k
  {
395
396
2.04M
  redo_char:
397
2.04M
    switch (state)
398
2.04M
    {
399
400
799k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
1.02M
      while (is_ws_char(c))
403
225k
      {
404
225k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
225k
      }
407
799k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
1.06k
      {
409
1.06k
        printbuf_reset(tok->pb);
410
1.06k
        printbuf_memappend_checked(tok->pb, &c, 1);
411
1.06k
        state = json_tokener_state_comment_start;
412
1.06k
      }
413
798k
      else
414
798k
      {
415
798k
        state = saved_state;
416
798k
        goto redo_char;
417
798k
      }
418
1.06k
      break;
419
420
145k
    case json_tokener_state_start:
421
145k
      switch (c)
422
145k
      {
423
47.9k
      case '{':
424
47.9k
        state = json_tokener_state_eatws;
425
47.9k
        saved_state = json_tokener_state_object_field_start;
426
47.9k
        current = json_object_new_object();
427
47.9k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
47.9k
        break;
433
47.9k
      case '[':
434
10.4k
        state = json_tokener_state_eatws;
435
10.4k
        saved_state = json_tokener_state_array;
436
10.4k
        current = json_object_new_array();
437
10.4k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
10.4k
        break;
443
10.4k
      case 'I':
444
14
      case 'i':
445
14
        state = json_tokener_state_inf;
446
14
        printbuf_reset(tok->pb);
447
14
        tok->st_pos = 0;
448
14
        goto redo_char;
449
140
      case 'N':
450
406
      case 'n':
451
406
        state = json_tokener_state_null; // or NaN
452
406
        printbuf_reset(tok->pb);
453
406
        tok->st_pos = 0;
454
406
        goto redo_char;
455
86
      case '\'':
456
86
        if (tok->flags & JSON_TOKENER_STRICT)
457
0
        {
458
          /* in STRICT mode only double-quote are allowed */
459
0
          tok->err = json_tokener_error_parse_unexpected;
460
0
          goto out;
461
0
        }
462
        /* FALLTHRU */
463
73.8k
      case '"':
464
73.8k
        state = json_tokener_state_string;
465
73.8k
        printbuf_reset(tok->pb);
466
73.8k
        tok->quote_char = c;
467
73.8k
        break;
468
24
      case 'T':
469
68
      case 't':
470
192
      case 'F':
471
318
      case 'f':
472
318
        state = json_tokener_state_boolean;
473
318
        printbuf_reset(tok->pb);
474
318
        tok->st_pos = 0;
475
318
        goto redo_char;
476
2.98k
      case '0':
477
5.68k
      case '1':
478
6.59k
      case '2':
479
6.98k
      case '3':
480
8.59k
      case '4':
481
9.25k
      case '5':
482
9.40k
      case '6':
483
9.54k
      case '7':
484
9.61k
      case '8':
485
10.0k
      case '9':
486
12.1k
      case '-':
487
12.1k
        state = json_tokener_state_number;
488
12.1k
        printbuf_reset(tok->pb);
489
12.1k
        tok->is_double = 0;
490
12.1k
        goto redo_char;
491
87
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
145k
      }
493
132k
      break;
494
495
143k
    case json_tokener_state_finish:
496
143k
      if (tok->depth == 0)
497
6.11k
        goto out;
498
137k
      obj = json_object_get(current);
499
137k
      json_tokener_reset_level(tok, tok->depth);
500
137k
      tok->depth--;
501
137k
      goto redo_char;
502
503
15
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
15
    {
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
15
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
39
      while (tok->st_pos < (int)json_inf_str_len)
516
39
      {
517
39
        char inf_char = *str;
518
39
        if (inf_char != json_inf_str[tok->st_pos] &&
519
29
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
29
              inf_char != json_inf_str_invert[tok->st_pos])
521
39
           )
522
15
        {
523
15
          tok->err = json_tokener_error_parse_unexpected;
524
15
          goto out;
525
15
        }
526
24
        tok->st_pos++;
527
24
        (void)ADVANCE_CHAR(str, tok);
528
24
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
24
      }
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.83k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.83k
    {
555
1.83k
      int size;
556
1.83k
      int size_nan;
557
1.83k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.83k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.83k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.83k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.83k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
427
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
1.41k
      {
564
1.41k
        if (tok->st_pos == json_null_str_len)
565
250
        {
566
250
          current = NULL;
567
250
          saved_state = json_tokener_state_finish;
568
250
          state = json_tokener_state_eatws;
569
250
          goto redo_char;
570
250
        }
571
1.41k
      }
572
427
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
427
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
22
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
405
      {
576
405
        if (tok->st_pos == json_nan_str_len)
577
134
        {
578
134
          current = json_object_new_double(NAN);
579
134
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
134
          saved_state = json_tokener_state_finish;
585
134
          state = json_tokener_state_eatws;
586
134
          goto redo_char;
587
134
        }
588
405
      }
589
22
      else
590
22
      {
591
22
        tok->err = json_tokener_error_parse_null;
592
22
        goto out;
593
22
      }
594
1.43k
      tok->st_pos++;
595
1.43k
    }
596
0
    break;
597
598
1.06k
    case json_tokener_state_comment_start:
599
1.06k
      if (c == '*')
600
280
      {
601
280
        state = json_tokener_state_comment;
602
280
      }
603
784
      else if (c == '/')
604
769
      {
605
769
        state = json_tokener_state_comment_eol;
606
769
      }
607
15
      else
608
15
      {
609
15
        tok->err = json_tokener_error_parse_comment;
610
15
        goto out;
611
15
      }
612
1.04k
      printbuf_memappend_checked(tok->pb, &c, 1);
613
1.04k
      break;
614
615
1.38k
    case json_tokener_state_comment:
616
1.38k
    {
617
      /* Advance until we change state */
618
1.38k
      const char *case_start = str;
619
24.9k
      while (c != '*')
620
23.6k
      {
621
23.6k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
622
26
        {
623
26
          printbuf_memappend_checked(tok->pb, case_start,
624
26
                                     str - case_start);
625
26
          goto out;
626
26
        }
627
23.6k
      }
628
1.35k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.35k
      state = json_tokener_state_comment_end;
630
1.35k
    }
631
0
    break;
632
633
769
    case json_tokener_state_comment_eol:
634
769
    {
635
      /* Advance until we change state */
636
769
      const char *case_start = str;
637
56.0k
      while (c != '\n')
638
55.3k
      {
639
55.3k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
40
        {
641
40
          printbuf_memappend_checked(tok->pb, case_start,
642
40
                                     str - case_start);
643
40
          goto out;
644
40
        }
645
55.3k
      }
646
729
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
729
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
729
      state = json_tokener_state_eatws;
649
729
    }
650
0
    break;
651
652
1.35k
    case json_tokener_state_comment_end:
653
1.35k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.35k
      if (c == '/')
655
250
      {
656
250
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
250
        state = json_tokener_state_eatws;
658
250
      }
659
1.10k
      else
660
1.10k
      {
661
1.10k
        state = json_tokener_state_comment;
662
1.10k
      }
663
1.35k
      break;
664
665
119k
    case json_tokener_state_string:
666
119k
    {
667
      /* Advance until we change state */
668
119k
      const char *case_start = str;
669
1.71M
      while (1)
670
1.71M
      {
671
1.71M
        if (c == tok->quote_char)
672
73.8k
        {
673
73.8k
          printbuf_memappend_checked(tok->pb, case_start,
674
73.8k
                                     str - case_start);
675
73.8k
          current =
676
73.8k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
73.8k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
73.8k
          saved_state = json_tokener_state_finish;
683
73.8k
          state = json_tokener_state_eatws;
684
73.8k
          break;
685
73.8k
        }
686
1.64M
        else if (c == '\\')
687
45.2k
        {
688
45.2k
          printbuf_memappend_checked(tok->pb, case_start,
689
45.2k
                                     str - case_start);
690
45.2k
          saved_state = json_tokener_state_string;
691
45.2k
          state = json_tokener_state_string_escape;
692
45.2k
          break;
693
45.2k
        }
694
1.59M
        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.59M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
44
        {
702
44
          printbuf_memappend_checked(tok->pb, case_start,
703
44
                                     str - case_start);
704
44
          goto out;
705
44
        }
706
1.59M
      }
707
119k
    }
708
119k
    break;
709
710
119k
    case json_tokener_state_string_escape:
711
52.1k
      switch (c)
712
52.1k
      {
713
9.93k
      case '"':
714
30.9k
      case '\\':
715
31.1k
      case '/':
716
31.1k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
31.1k
        state = saved_state;
718
31.1k
        break;
719
679
      case 'b':
720
17.6k
      case 'n':
721
17.9k
      case 'r':
722
18.5k
      case 't':
723
18.7k
      case 'f':
724
18.7k
        if (c == 'b')
725
679
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
18.0k
        else if (c == 'n')
727
16.9k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
1.10k
        else if (c == 'r')
729
283
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
826
        else if (c == 't')
731
588
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
238
        else if (c == 'f')
733
238
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
18.7k
        state = saved_state;
735
18.7k
        break;
736
2.25k
      case 'u':
737
2.25k
        tok->ucs_char = 0;
738
2.25k
        tok->st_pos = 0;
739
2.25k
        state = json_tokener_state_escape_unicode;
740
2.25k
        break;
741
11
      default: tok->err = json_tokener_error_parse_string; goto out;
742
52.1k
      }
743
52.1k
      break;
744
745
      // ===================================================
746
747
52.1k
    case json_tokener_state_escape_unicode:
748
2.68k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
10.7k
      while (1)
751
10.7k
      {
752
10.7k
        if (!c || !is_hex_char(c))
753
12
        {
754
12
          tok->err = json_tokener_error_parse_string;
755
12
          goto out;
756
12
        }
757
10.7k
        tok->ucs_char |=
758
10.7k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
10.7k
        tok->st_pos++;
760
10.7k
        if (tok->st_pos >= 4)
761
2.67k
          break;
762
763
8.04k
        (void)ADVANCE_CHAR(str, tok);
764
8.04k
        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
8.04k
      }
775
2.67k
      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.67k
      if (tok->high_surrogate)
781
430
      {
782
430
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
290
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
290
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
290
                                                tok->ucs_char);
787
290
        }
788
140
        else
789
140
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
140
          printbuf_memappend_checked(tok->pb,
794
140
                                     (char *)utf8_replacement_char, 3);
795
140
        }
796
430
        tok->high_surrogate = 0;
797
430
      }
798
799
2.67k
      if (tok->ucs_char < 0x80)
800
880
      {
801
880
        unsigned char unescaped_utf[1];
802
880
        unescaped_utf[0] = tok->ucs_char;
803
880
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
880
      }
805
1.79k
      else if (tok->ucs_char < 0x800)
806
40
      {
807
40
        unsigned char unescaped_utf[2];
808
40
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
809
40
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
810
40
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
811
40
      }
812
1.75k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
689
      {
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
689
        tok->high_surrogate = tok->ucs_char;
829
689
        tok->ucs_char = 0;
830
689
        state = json_tokener_state_escape_unicode_need_escape;
831
689
        break;
832
689
      }
833
1.06k
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
344
      {
835
        /* Got a low surrogate not preceded by a high */
836
344
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
344
      }
838
721
      else if (tok->ucs_char < 0x10000)
839
431
      {
840
431
        unsigned char unescaped_utf[3];
841
431
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
431
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
431
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
431
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
431
      }
846
290
      else if (tok->ucs_char < 0x110000)
847
290
      {
848
290
        unsigned char unescaped_utf[4];
849
290
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
290
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
290
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
290
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
290
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
290
      }
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.98k
      state = saved_state; // i.e. _state_string or _state_object_field
861
1.98k
    }
862
0
    break;
863
864
689
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
689
      if (!c || c != '\\')
868
155
      {
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
155
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
155
        tok->high_surrogate = 0;
875
155
        tok->ucs_char = 0;
876
155
        tok->st_pos = 0;
877
155
        state = saved_state;
878
155
        goto redo_char;
879
155
      }
880
534
      state = json_tokener_state_escape_unicode_need_u;
881
534
      break;
882
883
534
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
534
      if (!c || c != 'u')
886
102
      {
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
102
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
102
        tok->high_surrogate = 0;
894
102
        tok->ucs_char = 0;
895
102
        tok->st_pos = 0;
896
102
        state = json_tokener_state_string_escape;
897
102
        goto redo_char;
898
102
      }
899
432
      state = json_tokener_state_escape_unicode;
900
432
      break;
901
902
      // ===================================================
903
904
1.77k
    case json_tokener_state_boolean:
905
1.77k
    {
906
1.77k
      int size1, size2;
907
1.77k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.77k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.77k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.77k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.77k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.48k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
288
      {
914
288
        if (tok->st_pos == json_true_str_len)
915
54
        {
916
54
          current = json_object_new_boolean(1);
917
54
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
54
          saved_state = json_tokener_state_finish;
923
54
          state = json_tokener_state_eatws;
924
54
          goto redo_char;
925
54
        }
926
288
      }
927
1.48k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.48k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
24
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.46k
      {
931
1.46k
        if (tok->st_pos == json_false_str_len)
932
240
        {
933
240
          current = json_object_new_boolean(0);
934
240
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
240
          saved_state = json_tokener_state_finish;
940
240
          state = json_tokener_state_eatws;
941
240
          goto redo_char;
942
240
        }
943
1.46k
      }
944
24
      else
945
24
      {
946
24
        tok->err = json_tokener_error_parse_boolean;
947
24
        goto out;
948
24
      }
949
1.45k
      tok->st_pos++;
950
1.45k
    }
951
0
    break;
952
953
12.1k
    case json_tokener_state_number:
954
12.1k
    {
955
      /* Advance until we change state */
956
12.1k
      const char *case_start = str;
957
12.1k
      int case_len = 0;
958
12.1k
      int is_exponent = 0;
959
12.1k
      int neg_sign_ok = 1;
960
12.1k
      int pos_sign_ok = 0;
961
12.1k
      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
86.7k
      while (c && ((c >= '0' && c <= '9') ||
986
15.5k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
15.0k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
12.5k
                   (!tok->is_double && c == '.')))
989
74.6k
      {
990
74.6k
        pos_sign_ok = neg_sign_ok = 0;
991
74.6k
        ++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
74.6k
        switch (c)
1000
74.6k
        {
1001
477
        case '.':
1002
477
          tok->is_double = 1;
1003
477
          pos_sign_ok = 1;
1004
477
          neg_sign_ok = 1;
1005
477
          break;
1006
443
        case 'e': /* FALLTHRU */
1007
474
        case 'E':
1008
474
          is_exponent = 1;
1009
474
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
474
          pos_sign_ok = neg_sign_ok = 1;
1012
474
          break;
1013
73.6k
        default: break;
1014
74.6k
        }
1015
1016
74.6k
        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
74.6k
      }
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
12.1k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
957
          c != 'I' && c != 'i' && !is_ws_char(c))
1032
36
      {
1033
36
        tok->err = json_tokener_error_parse_number;
1034
36
        goto out;
1035
36
      }
1036
12.0k
      if (case_len > 0)
1037
12.0k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
12.0k
      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
12.0k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
550
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
1.17k
        while (printbuf_length(tok->pb) > 1)
1051
1.15k
        {
1052
1.15k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
1.15k
          if (last_char != 'e' && last_char != 'E' &&
1054
817
              last_char != '-' && last_char != '+')
1055
527
          {
1056
527
            break;
1057
527
          }
1058
628
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
628
          printbuf_length(tok->pb)--;
1060
628
        }
1061
550
      }
1062
12.0k
    }
1063
0
      {
1064
12.0k
        int64_t num64;
1065
12.0k
        uint64_t numuint64;
1066
12.0k
        double numd;
1067
12.0k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
1.62k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
1.61k
        {
1070
1.61k
          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.61k
          current = json_object_new_int64(num64);
1076
1.61k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
1.61k
        }
1082
10.4k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
9.91k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
9.91k
        {
1085
9.91k
          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
9.91k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
2.19k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
9.91k
          if (numuint64 <= INT64_MAX)
1097
9.41k
          {
1098
9.41k
            num64 = (uint64_t)numuint64;
1099
9.41k
            current = json_object_new_int64(num64);
1100
9.41k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
9.41k
          }
1106
496
          else
1107
496
          {
1108
496
            current = json_object_new_uint64(numuint64);
1109
496
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
496
          }
1115
9.91k
        }
1116
556
        else if (tok->is_double &&
1117
550
                 json_tokener_parse_double(
1118
550
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
549
        {
1120
549
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
549
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
549
        }
1127
7
        else
1128
7
        {
1129
7
          tok->err = json_tokener_error_parse_number;
1130
7
          goto out;
1131
7
        }
1132
12.0k
        saved_state = json_tokener_state_finish;
1133
12.0k
        state = json_tokener_state_eatws;
1134
12.0k
        goto redo_char;
1135
12.0k
      }
1136
0
      break;
1137
1138
21.0k
    case json_tokener_state_array_after_sep:
1139
31.4k
    case json_tokener_state_array:
1140
31.4k
      if (c == ']')
1141
367
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
367
        json_object_array_shrink(current, 0);
1144
1145
367
        if (state == json_tokener_state_array_after_sep &&
1146
26
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
367
        saved_state = json_tokener_state_finish;
1152
367
        state = json_tokener_state_eatws;
1153
367
      }
1154
31.1k
      else
1155
31.1k
      {
1156
31.1k
        if (tok->depth >= tok->max_depth - 1)
1157
1
        {
1158
1
          tok->err = json_tokener_error_depth;
1159
1
          goto out;
1160
1
        }
1161
31.1k
        state = json_tokener_state_array_add;
1162
31.1k
        tok->depth++;
1163
31.1k
        json_tokener_reset_level(tok, tok->depth);
1164
31.1k
        goto redo_char;
1165
31.1k
      }
1166
367
      break;
1167
1168
30.6k
    case json_tokener_state_array_add:
1169
30.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
30.6k
      saved_state = json_tokener_state_array_sep;
1175
30.6k
      state = json_tokener_state_eatws;
1176
30.6k
      goto redo_char;
1177
1178
30.6k
    case json_tokener_state_array_sep:
1179
30.6k
      if (c == ']')
1180
9.57k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
9.57k
        json_object_array_shrink(current, 0);
1183
1184
9.57k
        saved_state = json_tokener_state_finish;
1185
9.57k
        state = json_tokener_state_eatws;
1186
9.57k
      }
1187
21.1k
      else if (c == ',')
1188
21.0k
      {
1189
21.0k
        saved_state = json_tokener_state_array_after_sep;
1190
21.0k
        state = json_tokener_state_eatws;
1191
21.0k
      }
1192
26
      else
1193
26
      {
1194
26
        tok->err = json_tokener_error_parse_array;
1195
26
        goto out;
1196
26
      }
1197
30.6k
      break;
1198
1199
47.9k
    case json_tokener_state_object_field_start:
1200
125k
    case json_tokener_state_object_field_start_after_sep:
1201
125k
      if (c == '}')
1202
18.3k
      {
1203
18.3k
        if (state == json_tokener_state_object_field_start_after_sep &&
1204
4
            (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
107k
      else if (c == '"' || c == '\'')
1213
107k
      {
1214
107k
        tok->quote_char = c;
1215
107k
        printbuf_reset(tok->pb);
1216
107k
        state = json_tokener_state_object_field;
1217
107k
      }
1218
20
      else
1219
20
      {
1220
20
        tok->err = json_tokener_error_parse_object_key_name;
1221
20
        goto out;
1222
20
      }
1223
125k
      break;
1224
1225
125k
    case json_tokener_state_object_field:
1226
114k
    {
1227
      /* Advance until we change state */
1228
114k
      const char *case_start = str;
1229
935k
      while (1)
1230
935k
      {
1231
935k
        if (c == tok->quote_char)
1232
107k
        {
1233
107k
          printbuf_memappend_checked(tok->pb, case_start,
1234
107k
                                     str - case_start);
1235
107k
          obj_field_name = strdup(tok->pb->buf);
1236
107k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
107k
          saved_state = json_tokener_state_object_field_end;
1242
107k
          state = json_tokener_state_eatws;
1243
107k
          break;
1244
107k
        }
1245
827k
        else if (c == '\\')
1246
6.76k
        {
1247
6.76k
          printbuf_memappend_checked(tok->pb, case_start,
1248
6.76k
                                     str - case_start);
1249
6.76k
          saved_state = json_tokener_state_object_field;
1250
6.76k
          state = json_tokener_state_string_escape;
1251
6.76k
          break;
1252
6.76k
        }
1253
820k
        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
820k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
18
        {
1261
18
          printbuf_memappend_checked(tok->pb, case_start,
1262
18
                                     str - case_start);
1263
18
          goto out;
1264
18
        }
1265
820k
      }
1266
114k
    }
1267
114k
    break;
1268
1269
114k
    case json_tokener_state_object_field_end:
1270
107k
      if (c == ':')
1271
107k
      {
1272
107k
        saved_state = json_tokener_state_object_value;
1273
107k
        state = json_tokener_state_eatws;
1274
107k
      }
1275
19
      else
1276
19
      {
1277
19
        tok->err = json_tokener_error_parse_object_key_sep;
1278
19
        goto out;
1279
19
      }
1280
107k
      break;
1281
1282
107k
    case json_tokener_state_object_value:
1283
107k
      if (tok->depth >= tok->max_depth - 1)
1284
0
      {
1285
0
        tok->err = json_tokener_error_depth;
1286
0
        goto out;
1287
0
      }
1288
107k
      state = json_tokener_state_object_value_add;
1289
107k
      tok->depth++;
1290
107k
      json_tokener_reset_level(tok, tok->depth);
1291
107k
      goto redo_char;
1292
1293
106k
    case json_tokener_state_object_value_add:
1294
106k
      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
106k
      free(obj_field_name);
1300
106k
      obj_field_name = NULL;
1301
106k
      saved_state = json_tokener_state_object_sep;
1302
106k
      state = json_tokener_state_eatws;
1303
106k
      goto redo_char;
1304
1305
106k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
106k
      if (c == '}')
1308
28.8k
      {
1309
28.8k
        saved_state = json_tokener_state_finish;
1310
28.8k
        state = json_tokener_state_eatws;
1311
28.8k
      }
1312
78.0k
      else if (c == ',')
1313
78.0k
      {
1314
78.0k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
78.0k
        state = json_tokener_state_eatws;
1316
78.0k
      }
1317
15
      else
1318
15
      {
1319
15
        tok->err = json_tokener_error_parse_object_value_sep;
1320
15
        goto out;
1321
15
      }
1322
106k
      break;
1323
2.04M
    }
1324
801k
    (void)ADVANCE_CHAR(str, tok);
1325
801k
    if (!c) // This is the char *before* advancing
1326
4
      break;
1327
801k
  } /* while(PEEK_CHAR) */
1328
1329
6.55k
out:
1330
6.55k
  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.55k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
55
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
55
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
6.55k
  if (!c)
1342
6.29k
  {
1343
    /* We hit an eof char (0) */
1344
6.29k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
193
      tok->err = json_tokener_error_parse_eof;
1346
6.29k
  }
1347
1348
6.55k
#ifdef HAVE_USELOCALE
1349
6.55k
  uselocale(oldlocale);
1350
6.55k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
6.55k
  if (tok->err == json_tokener_success)
1357
6.15k
  {
1358
6.15k
    json_object *ret = json_object_get(current);
1359
6.15k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
12.3k
    for (ii = tok->depth; ii >= 0; ii--)
1363
6.19k
      json_tokener_reset_level(tok, ii);
1364
6.15k
    return ret;
1365
6.15k
  }
1366
1367
407
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
407
           tok->char_offset);
1369
407
  return NULL;
1370
6.55k
}
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
550
{
1411
550
  char *end;
1412
550
  *retval = strtod(buf, &end);
1413
550
  if (buf + len == end)
1414
549
    return 0; // It worked
1415
1
  return 1;
1416
550
}