Coverage Report

Created: 2026-02-11 06:19

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
9.46k
#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
880k
{
71
880k
  return c == ' '
72
727k
      || c == '\t'
73
709k
      || c == '\n'
74
707k
      || c == '\r';
75
880k
}
76
77
static inline int is_hex_char(char c)
78
9.47k
{
79
9.47k
  return (c >= '0' && c <= '9')
80
3.18k
      || (c >= 'A' && c <= 'F')
81
226
      || (c >= 'a' && c <= 'f');
82
9.47k
}
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
349
{
134
349
  int jerr_int = (int)jerr;
135
349
  if (jerr_int < 0 ||
136
349
      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
349
  return json_tokener_errors[jerr];
140
349
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
698
{
144
698
  return tok->err;
145
698
}
146
147
/* Stuff for decoding unicode sequences */
148
1.60k
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
1.36k
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
254
#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.11k
{
155
6.11k
  struct json_tokener *tok;
156
157
6.11k
  if (depth < 1)
158
0
    return NULL;
159
160
6.11k
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
6.11k
  if (!tok)
162
0
    return NULL;
163
6.11k
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
6.11k
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
6.11k
  tok->pb = printbuf_new();
170
6.11k
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
6.11k
  tok->max_depth = depth;
177
6.11k
  json_tokener_reset(tok);
178
6.11k
  return tok;
179
6.11k
}
180
181
struct json_tokener *json_tokener_new(void)
182
6.11k
{
183
6.11k
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
6.11k
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
6.11k
{
188
6.11k
  if (!tok)
189
0
    return;
190
6.11k
  json_tokener_reset(tok);
191
6.11k
  if (tok->pb)
192
6.11k
    printbuf_free(tok->pb);
193
6.11k
  free(tok->stack);
194
6.11k
  free(tok);
195
6.11k
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
260k
{
199
260k
  tok->stack[depth].state = json_tokener_state_eatws;
200
260k
  tok->stack[depth].saved_state = json_tokener_state_start;
201
260k
  json_object_put(tok->stack[depth].current);
202
260k
  tok->stack[depth].current = NULL;
203
260k
  free(tok->stack[depth].obj_field_name);
204
260k
  tok->stack[depth].obj_field_name = NULL;
205
260k
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
12.2k
{
209
12.2k
  int i;
210
12.2k
  if (!tok)
211
0
    return;
212
213
25.2k
  for (i = tok->depth; i >= 0; i--)
214
13.0k
    json_tokener_reset_level(tok, i);
215
12.2k
  tok->depth = 0;
216
12.2k
  tok->err = json_tokener_success;
217
12.2k
}
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.49M
#define state tok->stack[tok->depth].state
262
1.37M
#define saved_state tok->stack[tok->depth].saved_state
263
509k
#define current tok->stack[tok->depth].current
264
480k
#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.03M
  (((tok)->char_offset == len)                                         \
286
3.03M
       ? (((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.03M
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
291
3.03M
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
292
3.03M
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
293
3.03M
              : (((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.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
264k
  do {                                                  \
308
264k
    if (printbuf_memappend((p), (s), (l)) < 0)    \
309
264k
    {                                             \
310
0
      tok->err = json_tokener_error_memory; \
311
0
      goto out;                             \
312
0
    }                                             \
313
264k
  } 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.11k
{
319
6.11k
  struct json_object *obj = NULL;
320
6.11k
  char c = '\1';
321
6.11k
  unsigned int nBytes = 0;
322
6.11k
  unsigned int *nBytesp = &nBytes;
323
324
6.11k
#ifdef HAVE_USELOCALE
325
6.11k
  locale_t oldlocale = uselocale(NULL);
326
6.11k
  locale_t newloc;
327
#elif defined(HAVE_SETLOCALE)
328
  char *oldlocale = NULL;
329
#endif
330
331
6.11k
  tok->char_offset = 0;
332
6.11k
  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.11k
  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.11k
#ifdef HAVE_USELOCALE
347
6.11k
  {
348
6.11k
#ifdef HAVE_DUPLOCALE
349
6.11k
    locale_t duploc = duplocale(oldlocale);
350
6.11k
    if (duploc == NULL && errno == ENOMEM)
351
0
    {
352
0
      tok->err = json_tokener_error_memory;
353
0
      return NULL;
354
0
    }
355
6.11k
    newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);
356
#else
357
    newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);
358
#endif
359
6.11k
    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.11k
    uselocale(newloc);
375
6.11k
  }
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
711k
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
394
711k
  {
395
396
1.80M
  redo_char:
397
1.80M
    switch (state)
398
1.80M
    {
399
400
707k
    case json_tokener_state_eatws:
401
      /* Advance until we change state */
402
880k
      while (is_ws_char(c))
403
172k
      {
404
172k
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
405
0
          goto out;
406
172k
      }
407
707k
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
408
829
      {
409
829
        printbuf_reset(tok->pb);
410
829
        printbuf_memappend_checked(tok->pb, &c, 1);
411
829
        state = json_tokener_state_comment_start;
412
829
      }
413
706k
      else
414
706k
      {
415
706k
        state = saved_state;
416
706k
        goto redo_char;
417
706k
      }
418
829
      break;
419
420
127k
    case json_tokener_state_start:
421
127k
      switch (c)
422
127k
      {
423
44.4k
      case '{':
424
44.4k
        state = json_tokener_state_eatws;
425
44.4k
        saved_state = json_tokener_state_object_field_start;
426
44.4k
        current = json_object_new_object();
427
44.4k
        if (current == NULL)
428
0
        {
429
0
          tok->err = json_tokener_error_memory;
430
0
          goto out;
431
0
        }
432
44.4k
        break;
433
44.4k
      case '[':
434
8.45k
        state = json_tokener_state_eatws;
435
8.45k
        saved_state = json_tokener_state_array;
436
8.45k
        current = json_object_new_array();
437
8.45k
        if (current == NULL)
438
0
        {
439
0
          tok->err = json_tokener_error_memory;
440
0
          goto out;
441
0
        }
442
8.45k
        break;
443
8.45k
      case 'I':
444
10
      case 'i':
445
10
        state = json_tokener_state_inf;
446
10
        printbuf_reset(tok->pb);
447
10
        tok->st_pos = 0;
448
10
        goto redo_char;
449
127
      case 'N':
450
287
      case 'n':
451
287
        state = json_tokener_state_null; // or NaN
452
287
        printbuf_reset(tok->pb);
453
287
        tok->st_pos = 0;
454
287
        goto redo_char;
455
88
      case '\'':
456
88
        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
64.3k
      case '"':
464
64.3k
        state = json_tokener_state_string;
465
64.3k
        printbuf_reset(tok->pb);
466
64.3k
        tok->quote_char = c;
467
64.3k
        break;
468
23
      case 'T':
469
64
      case 't':
470
192
      case 'F':
471
305
      case 'f':
472
305
        state = json_tokener_state_boolean;
473
305
        printbuf_reset(tok->pb);
474
305
        tok->st_pos = 0;
475
305
        goto redo_char;
476
2.09k
      case '0':
477
4.34k
      case '1':
478
5.09k
      case '2':
479
5.42k
      case '3':
480
6.61k
      case '4':
481
7.16k
      case '5':
482
7.28k
      case '6':
483
7.40k
      case '7':
484
7.46k
      case '8':
485
7.77k
      case '9':
486
9.58k
      case '-':
487
9.58k
        state = json_tokener_state_number;
488
9.58k
        printbuf_reset(tok->pb);
489
9.58k
        tok->is_double = 0;
490
9.58k
        goto redo_char;
491
73
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
492
127k
      }
493
117k
      break;
494
495
126k
    case json_tokener_state_finish:
496
126k
      if (tok->depth == 0)
497
5.74k
        goto out;
498
120k
      obj = json_object_get(current);
499
120k
      json_tokener_reset_level(tok, tok->depth);
500
120k
      tok->depth--;
501
120k
      goto redo_char;
502
503
11
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
504
11
    {
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
11
      int is_negative = 0;
513
514
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
515
28
      while (tok->st_pos < (int)json_inf_str_len)
516
28
      {
517
28
        char inf_char = *str;
518
28
        if (inf_char != json_inf_str[tok->st_pos] &&
519
22
            ((tok->flags & JSON_TOKENER_STRICT) ||
520
22
              inf_char != json_inf_str_invert[tok->st_pos])
521
28
           )
522
11
        {
523
11
          tok->err = json_tokener_error_parse_unexpected;
524
11
          goto out;
525
11
        }
526
17
        tok->st_pos++;
527
17
        (void)ADVANCE_CHAR(str, tok);
528
17
        if (!PEEK_CHAR(c, tok))
529
0
        {
530
          /* out of input chars, for now at least */
531
0
          goto out;
532
0
        }
533
17
      }
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.27k
    case json_tokener_state_null: /* aka starts with 'n' */
554
1.27k
    {
555
1.27k
      int size;
556
1.27k
      int size_nan;
557
1.27k
      printbuf_memappend_checked(tok->pb, &c, 1);
558
1.27k
      size = json_min(tok->st_pos + 1, json_null_str_len);
559
1.27k
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
560
1.27k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
561
1.27k
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
562
389
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
563
881
      {
564
881
        if (tok->st_pos == json_null_str_len)
565
147
        {
566
147
          current = NULL;
567
147
          saved_state = json_tokener_state_finish;
568
147
          state = json_tokener_state_eatws;
569
147
          goto redo_char;
570
147
        }
571
881
      }
572
389
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
573
389
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
574
17
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
575
372
      {
576
372
        if (tok->st_pos == json_nan_str_len)
577
123
        {
578
123
          current = json_object_new_double(NAN);
579
123
          if (current == NULL)
580
0
          {
581
0
            tok->err = json_tokener_error_memory;
582
0
            goto out;
583
0
          }
584
123
          saved_state = json_tokener_state_finish;
585
123
          state = json_tokener_state_eatws;
586
123
          goto redo_char;
587
123
        }
588
372
      }
589
17
      else
590
17
      {
591
17
        tok->err = json_tokener_error_parse_null;
592
17
        goto out;
593
17
      }
594
983
      tok->st_pos++;
595
983
    }
596
0
    break;
597
598
829
    case json_tokener_state_comment_start:
599
829
      if (c == '*')
600
212
      {
601
212
        state = json_tokener_state_comment;
602
212
      }
603
617
      else if (c == '/')
604
606
      {
605
606
        state = json_tokener_state_comment_eol;
606
606
      }
607
11
      else
608
11
      {
609
11
        tok->err = json_tokener_error_parse_comment;
610
11
        goto out;
611
11
      }
612
818
      printbuf_memappend_checked(tok->pb, &c, 1);
613
818
      break;
614
615
1.18k
    case json_tokener_state_comment:
616
1.18k
    {
617
      /* Advance until we change state */
618
1.18k
      const char *case_start = str;
619
18.9k
      while (c != '*')
620
17.7k
      {
621
17.7k
        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
17.7k
      }
628
1.17k
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
629
1.17k
      state = json_tokener_state_comment_end;
630
1.17k
    }
631
0
    break;
632
633
606
    case json_tokener_state_comment_eol:
634
606
    {
635
      /* Advance until we change state */
636
606
      const char *case_start = str;
637
36.6k
      while (c != '\n')
638
36.0k
      {
639
36.0k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
640
34
        {
641
34
          printbuf_memappend_checked(tok->pb, case_start,
642
34
                                     str - case_start);
643
34
          goto out;
644
34
        }
645
36.0k
      }
646
572
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
647
572
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
648
572
      state = json_tokener_state_eatws;
649
572
    }
650
0
    break;
651
652
1.17k
    case json_tokener_state_comment_end:
653
1.17k
      printbuf_memappend_checked(tok->pb, &c, 1);
654
1.17k
      if (c == '/')
655
189
      {
656
189
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
657
189
        state = json_tokener_state_eatws;
658
189
      }
659
981
      else
660
981
      {
661
981
        state = json_tokener_state_comment;
662
981
      }
663
1.17k
      break;
664
665
101k
    case json_tokener_state_string:
666
101k
    {
667
      /* Advance until we change state */
668
101k
      const char *case_start = str;
669
1.40M
      while (1)
670
1.40M
      {
671
1.40M
        if (c == tok->quote_char)
672
64.3k
        {
673
64.3k
          printbuf_memappend_checked(tok->pb, case_start,
674
64.3k
                                     str - case_start);
675
64.3k
          current =
676
64.3k
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
677
64.3k
          if (current == NULL)
678
0
          {
679
0
            tok->err = json_tokener_error_memory;
680
0
            goto out;
681
0
          }
682
64.3k
          saved_state = json_tokener_state_finish;
683
64.3k
          state = json_tokener_state_eatws;
684
64.3k
          break;
685
64.3k
        }
686
1.34M
        else if (c == '\\')
687
36.8k
        {
688
36.8k
          printbuf_memappend_checked(tok->pb, case_start,
689
36.8k
                                     str - case_start);
690
36.8k
          saved_state = json_tokener_state_string;
691
36.8k
          state = json_tokener_state_string_escape;
692
36.8k
          break;
693
36.8k
        }
694
1.30M
        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.30M
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
701
37
        {
702
37
          printbuf_memappend_checked(tok->pb, case_start,
703
37
                                     str - case_start);
704
37
          goto out;
705
37
        }
706
1.30M
      }
707
101k
    }
708
101k
    break;
709
710
101k
    case json_tokener_state_string_escape:
711
43.4k
      switch (c)
712
43.4k
      {
713
8.30k
      case '"':
714
25.5k
      case '\\':
715
25.6k
      case '/':
716
25.6k
        printbuf_memappend_checked(tok->pb, &c, 1);
717
25.6k
        state = saved_state;
718
25.6k
        break;
719
657
      case 'b':
720
14.7k
      case 'n':
721
15.0k
      case 'r':
722
15.5k
      case 't':
723
15.7k
      case 'f':
724
15.7k
        if (c == 'b')
725
657
          printbuf_memappend_checked(tok->pb, "\b", 1);
726
15.0k
        else if (c == 'n')
727
14.1k
          printbuf_memappend_checked(tok->pb, "\n", 1);
728
936
        else if (c == 'r')
729
275
          printbuf_memappend_checked(tok->pb, "\r", 1);
730
661
        else if (c == 't')
731
500
          printbuf_memappend_checked(tok->pb, "\t", 1);
732
161
        else if (c == 'f')
733
161
          printbuf_memappend_checked(tok->pb, "\f", 1);
734
15.7k
        state = saved_state;
735
15.7k
        break;
736
1.99k
      case 'u':
737
1.99k
        tok->ucs_char = 0;
738
1.99k
        tok->st_pos = 0;
739
1.99k
        state = json_tokener_state_escape_unicode;
740
1.99k
        break;
741
11
      default: tok->err = json_tokener_error_parse_string; goto out;
742
43.4k
      }
743
43.3k
      break;
744
745
      // ===================================================
746
747
43.3k
    case json_tokener_state_escape_unicode:
748
2.37k
    {
749
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
750
9.48k
      while (1)
751
9.48k
      {
752
9.48k
        if (!c || !is_hex_char(c))
753
12
        {
754
12
          tok->err = json_tokener_error_parse_string;
755
12
          goto out;
756
12
        }
757
9.46k
        tok->ucs_char |=
758
9.46k
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
759
9.46k
        tok->st_pos++;
760
9.46k
        if (tok->st_pos >= 4)
761
2.36k
          break;
762
763
7.10k
        (void)ADVANCE_CHAR(str, tok);
764
7.10k
        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
7.10k
      }
775
2.36k
      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.36k
      if (tok->high_surrogate)
781
378
      {
782
378
        if (IS_LOW_SURROGATE(tok->ucs_char))
783
254
        {
784
          /* Recalculate the ucs_char, then fall thru to process normally */
785
254
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
786
254
                                                tok->ucs_char);
787
254
        }
788
124
        else
789
124
        {
790
          /* High surrogate was not followed by a low surrogate
791
           * Replace the high and process the rest normally
792
           */
793
124
          printbuf_memappend_checked(tok->pb,
794
124
                                     (char *)utf8_replacement_char, 3);
795
124
        }
796
378
        tok->high_surrogate = 0;
797
378
      }
798
799
2.36k
      if (tok->ucs_char < 0x80)
800
714
      {
801
714
        unsigned char unescaped_utf[1];
802
714
        unescaped_utf[0] = tok->ucs_char;
803
714
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
804
714
      }
805
1.64k
      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.60k
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
813
616
      {
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
616
        tok->high_surrogate = tok->ucs_char;
829
616
        tok->ucs_char = 0;
830
616
        state = json_tokener_state_escape_unicode_need_escape;
831
616
        break;
832
616
      }
833
990
      else if (IS_LOW_SURROGATE(tok->ucs_char))
834
336
      {
835
        /* Got a low surrogate not preceded by a high */
836
336
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
837
336
      }
838
654
      else if (tok->ucs_char < 0x10000)
839
400
      {
840
400
        unsigned char unescaped_utf[3];
841
400
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
842
400
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
843
400
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
844
400
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
845
400
      }
846
254
      else if (tok->ucs_char < 0x110000)
847
254
      {
848
254
        unsigned char unescaped_utf[4];
849
254
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
850
254
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
851
254
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
852
254
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
853
254
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
854
254
      }
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.74k
      state = saved_state; // i.e. _state_string or _state_object_field
861
1.74k
    }
862
0
    break;
863
864
616
    case json_tokener_state_escape_unicode_need_escape:
865
      // We get here after processing a high_surrogate
866
      // require a '\\' char
867
616
      if (!c || c != '\\')
868
145
      {
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
145
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
874
145
        tok->high_surrogate = 0;
875
145
        tok->ucs_char = 0;
876
145
        tok->st_pos = 0;
877
145
        state = saved_state;
878
145
        goto redo_char;
879
145
      }
880
471
      state = json_tokener_state_escape_unicode_need_u;
881
471
      break;
882
883
471
    case json_tokener_state_escape_unicode_need_u:
884
      /* We already had a \ char, check that it's \u */
885
471
      if (!c || c != 'u')
886
91
      {
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
91
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
893
91
        tok->high_surrogate = 0;
894
91
        tok->ucs_char = 0;
895
91
        tok->st_pos = 0;
896
91
        state = json_tokener_state_string_escape;
897
91
        goto redo_char;
898
91
      }
899
380
      state = json_tokener_state_escape_unicode;
900
380
      break;
901
902
      // ===================================================
903
904
1.70k
    case json_tokener_state_boolean:
905
1.70k
    {
906
1.70k
      int size1, size2;
907
1.70k
      printbuf_memappend_checked(tok->pb, &c, 1);
908
1.70k
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
909
1.70k
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
910
1.70k
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
911
1.70k
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
912
1.42k
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
913
276
      {
914
276
        if (tok->st_pos == json_true_str_len)
915
52
        {
916
52
          current = json_object_new_boolean(1);
917
52
          if (current == NULL)
918
0
          {
919
0
            tok->err = json_tokener_error_memory;
920
0
            goto out;
921
0
          }
922
52
          saved_state = json_tokener_state_finish;
923
52
          state = json_tokener_state_eatws;
924
52
          goto redo_char;
925
52
        }
926
276
      }
927
1.42k
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
928
1.42k
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
929
23
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
930
1.40k
      {
931
1.40k
        if (tok->st_pos == json_false_str_len)
932
230
        {
933
230
          current = json_object_new_boolean(0);
934
230
          if (current == NULL)
935
0
          {
936
0
            tok->err = json_tokener_error_memory;
937
0
            goto out;
938
0
          }
939
230
          saved_state = json_tokener_state_finish;
940
230
          state = json_tokener_state_eatws;
941
230
          goto redo_char;
942
230
        }
943
1.40k
      }
944
23
      else
945
23
      {
946
23
        tok->err = json_tokener_error_parse_boolean;
947
23
        goto out;
948
23
      }
949
1.39k
      tok->st_pos++;
950
1.39k
    }
951
0
    break;
952
953
9.58k
    case json_tokener_state_number:
954
9.58k
    {
955
      /* Advance until we change state */
956
9.58k
      const char *case_start = str;
957
9.58k
      int case_len = 0;
958
9.58k
      int is_exponent = 0;
959
9.58k
      int neg_sign_ok = 1;
960
9.58k
      int pos_sign_ok = 0;
961
9.58k
      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
66.9k
      while (c && ((c >= '0' && c <= '9') ||
986
12.5k
                   (!is_exponent && (c == 'e' || c == 'E')) ||
987
12.1k
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
988
9.97k
                   (!tok->is_double && c == '.')))
989
57.4k
      {
990
57.4k
        pos_sign_ok = neg_sign_ok = 0;
991
57.4k
        ++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
57.4k
        switch (c)
1000
57.4k
        {
1001
420
        case '.':
1002
420
          tok->is_double = 1;
1003
420
          pos_sign_ok = 1;
1004
420
          neg_sign_ok = 1;
1005
420
          break;
1006
399
        case 'e': /* FALLTHRU */
1007
425
        case 'E':
1008
425
          is_exponent = 1;
1009
425
          tok->is_double = 1;
1010
          /* the exponent part can begin with a negative sign */
1011
425
          pos_sign_ok = neg_sign_ok = 1;
1012
425
          break;
1013
56.5k
        default: break;
1014
57.4k
        }
1015
1016
57.4k
        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
57.4k
      }
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.58k
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1031
849
          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
9.55k
      if (case_len > 0)
1037
9.55k
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1038
1039
      // Check for -Infinity
1040
9.55k
      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.54k
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1047
480
      {
1048
        /* Trim some chars off the end, to allow things
1049
           like "123e+" to parse ok. */
1050
1.14k
        while (printbuf_length(tok->pb) > 1)
1051
1.11k
        {
1052
1.11k
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1053
1.11k
          if (last_char != 'e' && last_char != 'E' &&
1054
770
              last_char != '-' && last_char != '+')
1055
457
          {
1056
457
            break;
1057
457
          }
1058
662
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1059
662
          printbuf_length(tok->pb)--;
1060
662
        }
1061
480
      }
1062
9.54k
    }
1063
0
      {
1064
9.54k
        int64_t num64;
1065
9.54k
        uint64_t numuint64;
1066
9.54k
        double numd;
1067
9.54k
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1068
1.41k
            json_parse_int64(tok->pb->buf, &num64) == 0)
1069
1.40k
        {
1070
1.40k
          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.40k
          current = json_object_new_int64(num64);
1076
1.40k
          if (current == NULL)
1077
0
          {
1078
0
            tok->err = json_tokener_error_memory;
1079
0
            goto out;
1080
0
          }
1081
1.40k
        }
1082
8.14k
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1083
7.65k
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1084
7.65k
        {
1085
7.65k
          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.65k
          if (numuint64 && tok->pb->buf[0] == '0' &&
1091
1.37k
              (tok->flags & JSON_TOKENER_STRICT))
1092
0
          {
1093
0
            tok->err = json_tokener_error_parse_number;
1094
0
            goto out;
1095
0
          }
1096
7.65k
          if (numuint64 <= INT64_MAX)
1097
7.31k
          {
1098
7.31k
            num64 = (uint64_t)numuint64;
1099
7.31k
            current = json_object_new_int64(num64);
1100
7.31k
            if (current == NULL)
1101
0
            {
1102
0
              tok->err = json_tokener_error_memory;
1103
0
              goto out;
1104
0
            }
1105
7.31k
          }
1106
341
          else
1107
341
          {
1108
341
            current = json_object_new_uint64(numuint64);
1109
341
            if (current == NULL)
1110
0
            {
1111
0
              tok->err = json_tokener_error_memory;
1112
0
              goto out;
1113
0
            }
1114
341
          }
1115
7.65k
        }
1116
483
        else if (tok->is_double &&
1117
480
                 json_tokener_parse_double(
1118
480
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1119
479
        {
1120
479
          current = json_object_new_double_s(numd, tok->pb->buf);
1121
479
          if (current == NULL)
1122
0
          {
1123
0
            tok->err = json_tokener_error_memory;
1124
0
            goto out;
1125
0
          }
1126
479
        }
1127
4
        else
1128
4
        {
1129
4
          tok->err = json_tokener_error_parse_number;
1130
4
          goto out;
1131
4
        }
1132
9.54k
        saved_state = json_tokener_state_finish;
1133
9.54k
        state = json_tokener_state_eatws;
1134
9.54k
        goto redo_char;
1135
9.54k
      }
1136
0
      break;
1137
1138
16.8k
    case json_tokener_state_array_after_sep:
1139
25.3k
    case json_tokener_state_array:
1140
25.3k
      if (c == ']')
1141
215
      {
1142
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1143
215
        json_object_array_shrink(current, 0);
1144
1145
215
        if (state == json_tokener_state_array_after_sep &&
1146
17
            (tok->flags & JSON_TOKENER_STRICT))
1147
0
        {
1148
0
          tok->err = json_tokener_error_parse_unexpected;
1149
0
          goto out;
1150
0
        }
1151
215
        saved_state = json_tokener_state_finish;
1152
215
        state = json_tokener_state_eatws;
1153
215
      }
1154
25.1k
      else
1155
25.1k
      {
1156
25.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
25.1k
        state = json_tokener_state_array_add;
1162
25.1k
        tok->depth++;
1163
25.1k
        json_tokener_reset_level(tok, tok->depth);
1164
25.1k
        goto redo_char;
1165
25.1k
      }
1166
215
      break;
1167
1168
24.8k
    case json_tokener_state_array_add:
1169
24.8k
      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
24.8k
      saved_state = json_tokener_state_array_sep;
1175
24.8k
      state = json_tokener_state_eatws;
1176
24.8k
      goto redo_char;
1177
1178
24.8k
    case json_tokener_state_array_sep:
1179
24.8k
      if (c == ']')
1180
7.91k
      {
1181
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1182
7.91k
        json_object_array_shrink(current, 0);
1183
1184
7.91k
        saved_state = json_tokener_state_finish;
1185
7.91k
        state = json_tokener_state_eatws;
1186
7.91k
      }
1187
16.8k
      else if (c == ',')
1188
16.8k
      {
1189
16.8k
        saved_state = json_tokener_state_array_after_sep;
1190
16.8k
        state = json_tokener_state_eatws;
1191
16.8k
      }
1192
17
      else
1193
17
      {
1194
17
        tok->err = json_tokener_error_parse_array;
1195
17
        goto out;
1196
17
      }
1197
24.7k
      break;
1198
1199
44.4k
    case json_tokener_state_object_field_start:
1200
113k
    case json_tokener_state_object_field_start_after_sep:
1201
113k
      if (c == '}')
1202
17.2k
      {
1203
17.2k
        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
17.2k
        saved_state = json_tokener_state_finish;
1210
17.2k
        state = json_tokener_state_eatws;
1211
17.2k
      }
1212
96.4k
      else if (c == '"' || c == '\'')
1213
96.3k
      {
1214
96.3k
        tok->quote_char = c;
1215
96.3k
        printbuf_reset(tok->pb);
1216
96.3k
        state = json_tokener_state_object_field;
1217
96.3k
      }
1218
15
      else
1219
15
      {
1220
15
        tok->err = json_tokener_error_parse_object_key_name;
1221
15
        goto out;
1222
15
      }
1223
113k
      break;
1224
1225
113k
    case json_tokener_state_object_field:
1226
102k
    {
1227
      /* Advance until we change state */
1228
102k
      const char *case_start = str;
1229
829k
      while (1)
1230
829k
      {
1231
829k
        if (c == tok->quote_char)
1232
96.3k
        {
1233
96.3k
          printbuf_memappend_checked(tok->pb, case_start,
1234
96.3k
                                     str - case_start);
1235
96.3k
          obj_field_name = strdup(tok->pb->buf);
1236
96.3k
          if (obj_field_name == NULL)
1237
0
          {
1238
0
            tok->err = json_tokener_error_memory;
1239
0
            goto out;
1240
0
          }
1241
96.3k
          saved_state = json_tokener_state_object_field_end;
1242
96.3k
          state = json_tokener_state_eatws;
1243
96.3k
          break;
1244
96.3k
        }
1245
732k
        else if (c == '\\')
1246
6.47k
        {
1247
6.47k
          printbuf_memappend_checked(tok->pb, case_start,
1248
6.47k
                                     str - case_start);
1249
6.47k
          saved_state = json_tokener_state_object_field;
1250
6.47k
          state = json_tokener_state_string_escape;
1251
6.47k
          break;
1252
6.47k
        }
1253
726k
        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
726k
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1260
16
        {
1261
16
          printbuf_memappend_checked(tok->pb, case_start,
1262
16
                                     str - case_start);
1263
16
          goto out;
1264
16
        }
1265
726k
      }
1266
102k
    }
1267
102k
    break;
1268
1269
102k
    case json_tokener_state_object_field_end:
1270
96.3k
      if (c == ':')
1271
96.3k
      {
1272
96.3k
        saved_state = json_tokener_state_object_value;
1273
96.3k
        state = json_tokener_state_eatws;
1274
96.3k
      }
1275
13
      else
1276
13
      {
1277
13
        tok->err = json_tokener_error_parse_object_key_sep;
1278
13
        goto out;
1279
13
      }
1280
96.3k
      break;
1281
1282
96.3k
    case json_tokener_state_object_value:
1283
96.3k
      if (tok->depth >= tok->max_depth - 1)
1284
0
      {
1285
0
        tok->err = json_tokener_error_depth;
1286
0
        goto out;
1287
0
      }
1288
96.3k
      state = json_tokener_state_object_value_add;
1289
96.3k
      tok->depth++;
1290
96.3k
      json_tokener_reset_level(tok, tok->depth);
1291
96.3k
      goto redo_char;
1292
1293
95.8k
    case json_tokener_state_object_value_add:
1294
95.8k
      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
95.8k
      free(obj_field_name);
1300
95.8k
      obj_field_name = NULL;
1301
95.8k
      saved_state = json_tokener_state_object_sep;
1302
95.8k
      state = json_tokener_state_eatws;
1303
95.8k
      goto redo_char;
1304
1305
95.8k
    case json_tokener_state_object_sep:
1306
      /* { */
1307
95.8k
      if (c == '}')
1308
26.6k
      {
1309
26.6k
        saved_state = json_tokener_state_finish;
1310
26.6k
        state = json_tokener_state_eatws;
1311
26.6k
      }
1312
69.2k
      else if (c == ',')
1313
69.2k
      {
1314
69.2k
        saved_state = json_tokener_state_object_field_start_after_sep;
1315
69.2k
        state = json_tokener_state_eatws;
1316
69.2k
      }
1317
18
      else
1318
18
      {
1319
18
        tok->err = json_tokener_error_parse_object_value_sep;
1320
18
        goto out;
1321
18
      }
1322
95.8k
      break;
1323
1.80M
    }
1324
705k
    (void)ADVANCE_CHAR(str, tok);
1325
705k
    if (!c) // This is the char *before* advancing
1326
4
      break;
1327
705k
  } /* while(PEEK_CHAR) */
1328
1329
6.11k
out:
1330
6.11k
  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.11k
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1335
50
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1336
50
          JSON_TOKENER_STRICT)
1337
0
  {
1338
    /* unexpected char after JSON data */
1339
0
    tok->err = json_tokener_error_parse_unexpected;
1340
0
  }
1341
6.11k
  if (!c)
1342
5.87k
  {
1343
    /* We hit an eof char (0) */
1344
5.87k
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1345
157
      tok->err = json_tokener_error_parse_eof;
1346
5.87k
  }
1347
1348
6.11k
#ifdef HAVE_USELOCALE
1349
6.11k
  uselocale(oldlocale);
1350
6.11k
  freelocale(newloc);
1351
#elif defined(HAVE_SETLOCALE)
1352
  setlocale(LC_NUMERIC, oldlocale);
1353
  free(oldlocale);
1354
#endif
1355
1356
6.11k
  if (tok->err == json_tokener_success)
1357
5.76k
  {
1358
5.76k
    json_object *ret = json_object_get(current);
1359
5.76k
    int ii;
1360
1361
    /* Partially reset, so we parse additional objects on subsequent calls. */
1362
11.5k
    for (ii = tok->depth; ii >= 0; ii--)
1363
5.80k
      json_tokener_reset_level(tok, ii);
1364
5.76k
    return ret;
1365
5.76k
  }
1366
1367
348
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1368
348
           tok->char_offset);
1369
348
  return NULL;
1370
6.11k
}
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
480
{
1411
480
  char *end;
1412
480
  *retval = strtod(buf, &end);
1413
480
  if (buf + len == end)
1414
479
    return 0; // It worked
1415
1
  return 1;
1416
480
}