Coverage Report

Created: 2026-10-28 07:06

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
0
#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
0
{
71
0
  return c == ' '
72
0
      || c == '\t'
73
0
      || c == '\n'
74
0
      || c == '\r';
75
0
}
76
77
static inline int is_hex_char(char c)
78
0
{
79
0
  return (c >= '0' && c <= '9')
80
0
      || (c >= 'A' && c <= 'F')
81
0
      || (c >= 'a' && c <= 'f');
82
0
}
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
0
{
134
0
  int jerr_int = (int)jerr;
135
0
  if (jerr_int < 0 ||
136
0
      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
0
  return json_tokener_errors[jerr];
140
0
}
141
142
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
143
0
{
144
0
  return tok->err;
145
0
}
146
147
/* Stuff for decoding unicode sequences */
148
0
#define IS_HIGH_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xD800)
149
0
#define IS_LOW_SURROGATE(uc) (((uc)&0xFFFFFC00) == 0xDC00)
150
0
#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
0
{
155
0
  struct json_tokener *tok;
156
157
0
  if (depth < 1)
158
0
    return NULL;
159
160
0
  tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));
161
0
  if (!tok)
162
0
    return NULL;
163
0
  tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
164
0
  if (!tok->stack)
165
0
  {
166
0
    free(tok);
167
0
    return NULL;
168
0
  }
169
0
  tok->pb = printbuf_new();
170
0
  if (!tok->pb)
171
0
  {
172
0
    free(tok->stack);
173
0
    free(tok);
174
0
    return NULL;
175
0
  }
176
0
  tok->max_depth = depth;
177
0
  json_tokener_reset(tok);
178
0
  return tok;
179
0
}
180
181
struct json_tokener *json_tokener_new(void)
182
0
{
183
0
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
184
0
}
185
186
void json_tokener_free(struct json_tokener *tok)
187
0
{
188
0
  if (!tok)
189
0
    return;
190
0
  json_tokener_reset(tok);
191
0
  if (tok->pb)
192
0
    printbuf_free(tok->pb);
193
0
  free(tok->stack);
194
0
  free(tok);
195
0
}
196
197
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
198
0
{
199
0
  tok->stack[depth].state = json_tokener_state_eatws;
200
0
  tok->stack[depth].saved_state = json_tokener_state_start;
201
0
  json_object_put(tok->stack[depth].current);
202
0
  tok->stack[depth].current = NULL;
203
0
  free(tok->stack[depth].obj_field_name);
204
0
  tok->stack[depth].obj_field_name = NULL;
205
0
}
206
207
void json_tokener_reset(struct json_tokener *tok)
208
0
{
209
0
  int i;
210
0
  if (!tok)
211
0
    return;
212
213
0
  for (i = tok->depth; i >= 0; i--)
214
0
    json_tokener_reset_level(tok, i);
215
0
  tok->depth = 0;
216
0
  tok->err = json_tokener_success;
217
0
  tok->high_surrogate = 0;
218
0
}
219
220
struct json_object *json_tokener_parse(const char *str)
221
0
{
222
0
  enum json_tokener_error jerr_ignored;
223
0
  struct json_object *obj;
224
0
  obj = json_tokener_parse_verbose(str, &jerr_ignored);
225
0
  return obj;
226
0
}
227
228
struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
229
0
{
230
0
  struct json_tokener *tok;
231
0
  struct json_object *obj;
232
233
0
  tok = json_tokener_new();
234
0
  if (!tok)
235
0
  {
236
0
    *error = json_tokener_error_memory;
237
0
    return NULL;
238
0
  }
239
0
  obj = json_tokener_parse_ex(tok, str, -1);
240
0
  *error = tok->err;
241
0
  if (tok->err != json_tokener_success
242
#if 0
243
    /* This would be a more sensible default, and cause parsing
244
     * things like "null123" to fail when the caller can't know
245
     * where the parsing left off, but starting to fail would
246
     * be a notable behaviour change.  Save for a 1.0 release.
247
     */
248
      || json_tokener_get_parse_end(tok) != strlen(str)
249
#endif
250
0
  )
251
252
0
  {
253
0
    if (obj != NULL)
254
0
      json_object_put(obj);
255
0
    obj = NULL;
256
0
  }
257
258
0
  json_tokener_free(tok);
259
0
  return obj;
260
0
}
261
262
0
#define state tok->stack[tok->depth].state
263
0
#define saved_state tok->stack[tok->depth].saved_state
264
0
#define current tok->stack[tok->depth].current
265
0
#define obj_field_name tok->stack[tok->depth].obj_field_name
266
267
/* Optimization:
268
 * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
269
 * iterating character-by character.  A large performance boost is
270
 * achieved by using tighter loops to locally handle units such as
271
 * comments and strings.  Loops that handle an entire token within
272
 * their scope also gather entire strings and pass them to
273
 * printbuf_memappend() in a single call, rather than calling
274
 * printbuf_memappend() one char at a time.
275
 *
276
 * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
277
 * common to both the main loop and the tighter loops.
278
 */
279
280
/* PEEK_CHAR(dest, tok) macro:
281
 *   Peeks at the current char and stores it in dest.
282
 *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
283
 *   Implicit inputs:  str, len, nBytesp vars
284
 */
285
#define PEEK_CHAR(dest, tok)                                                 \
286
0
  (((tok)->char_offset == len)                                         \
287
0
       ? (((tok)->depth == 0 && state == json_tokener_state_eatws &&   \
288
0
           saved_state == json_tokener_state_finish)                   \
289
0
              ? (((tok)->err = json_tokener_success), 0)               \
290
0
              : (((tok)->err = json_tokener_continue), 0))             \
291
0
       : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \
292
0
           (!json_tokener_validate_utf8(*str, nBytesp)))               \
293
0
              ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \
294
0
              : (((dest) = *str), 1)))
295
296
/* ADVANCE_CHAR() macro:
297
 *   Increments str & tok->char_offset.
298
 *   For convenience of existing conditionals, returns the old value of c (0 on eof).
299
 *   Implicit inputs:  c var
300
 */
301
0
#define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c)
302
303
/* printbuf_memappend_checked(p, s, l) macro:
304
 *   Add string s of length l to printbuffer p.
305
 *   If operation fails abort parse operation with memory error.
306
 */
307
#define printbuf_memappend_checked(p, s, l)                   \
308
0
  do {                                                  \
309
0
    if (printbuf_memappend((p), (s), (l)) < 0)    \
310
0
    {                                             \
311
0
      tok->err = json_tokener_error_memory; \
312
0
      goto out;                             \
313
0
    }                                             \
314
0
  } while (0)
315
316
/* End optimization macro defs */
317
318
#ifdef HAVE_USELOCALE
319
/* One-time C-numeric locale, created on first call and reused forever.
320
 * Avoids per-call duplocale() overhead and the memory leak seen on AIX
321
 * where freelocale() does not release all locale category memory.
322
 * Freed on library unload by json_tokener_locale_fini().
323
 */
324
static locale_t c_numeric_locale = (locale_t)0;
325
#endif /* HAVE_USELOCALE */
326
327
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len)
328
0
{
329
0
  struct json_object *obj = NULL;
330
0
  char c = '\1';
331
0
  unsigned int nBytes = 0;
332
0
  unsigned int *nBytesp = &nBytes;
333
334
0
#ifdef HAVE_USELOCALE
335
0
  locale_t oldlocale = uselocale(NULL);
336
#elif defined(HAVE_SETLOCALE)
337
  char *oldlocale = NULL;
338
#endif
339
340
0
  tok->char_offset = 0;
341
0
  tok->err = json_tokener_success;
342
343
  /* this interface is presently not 64-bit clean due to the int len argument
344
   * and the internal printbuf interface that takes 32-bit int len arguments
345
   * so the function limits the maximum string size to INT32_MAX (2GB).
346
   * If the function is called with len == -1 then strlen is called to check
347
   * the string length is less than INT32_MAX (2GB)
348
   */
349
0
  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX))
350
0
  {
351
0
    tok->err = json_tokener_error_size;
352
0
    return NULL;
353
0
  }
354
355
0
#ifdef HAVE_USELOCALE
356
0
  {
357
0
    if (c_numeric_locale == (locale_t)0)
358
0
    {
359
0
      c_numeric_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
360
0
      if (c_numeric_locale == (locale_t)0)
361
0
      {
362
0
        tok->err = json_tokener_error_memory;
363
0
        return NULL;
364
0
      }
365
0
    }
366
0
    uselocale(c_numeric_locale);
367
0
  }
368
#elif defined(HAVE_SETLOCALE)
369
  {
370
    char *tmplocale;
371
    tmplocale = setlocale(LC_NUMERIC, NULL);
372
    if (tmplocale)
373
    {
374
      oldlocale = strdup(tmplocale);
375
      if (oldlocale == NULL)
376
      {
377
        tok->err = json_tokener_error_memory;
378
        return NULL;
379
      }
380
    }
381
    setlocale(LC_NUMERIC, "C");
382
  }
383
#endif
384
385
0
  while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !
386
0
  {
387
388
0
  redo_char:
389
0
    switch (state)
390
0
    {
391
392
0
    case json_tokener_state_eatws:
393
      /* Advance until we change state */
394
0
      while (is_ws_char(c))
395
0
      {
396
0
        if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
397
0
          goto out;
398
0
      }
399
0
      if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))
400
0
      {
401
0
        printbuf_reset(tok->pb);
402
0
        printbuf_memappend_checked(tok->pb, &c, 1);
403
0
        state = json_tokener_state_comment_start;
404
0
      }
405
0
      else
406
0
      {
407
0
        state = saved_state;
408
0
        goto redo_char;
409
0
      }
410
0
      break;
411
412
0
    case json_tokener_state_start:
413
0
      switch (c)
414
0
      {
415
0
      case '{':
416
0
        state = json_tokener_state_eatws;
417
0
        saved_state = json_tokener_state_object_field_start;
418
0
        current = json_object_new_object();
419
0
        if (current == NULL)
420
0
        {
421
0
          tok->err = json_tokener_error_memory;
422
0
          goto out;
423
0
        }
424
0
        break;
425
0
      case '[':
426
0
        state = json_tokener_state_eatws;
427
0
        saved_state = json_tokener_state_array;
428
0
        current = json_object_new_array();
429
0
        if (current == NULL)
430
0
        {
431
0
          tok->err = json_tokener_error_memory;
432
0
          goto out;
433
0
        }
434
0
        break;
435
0
      case 'I':
436
0
      case 'i':
437
0
        state = json_tokener_state_inf;
438
0
        printbuf_reset(tok->pb);
439
0
        tok->st_pos = 0;
440
0
        goto redo_char;
441
0
      case 'N':
442
0
      case 'n':
443
0
        state = json_tokener_state_null; // or NaN
444
0
        printbuf_reset(tok->pb);
445
0
        tok->st_pos = 0;
446
0
        goto redo_char;
447
0
      case '\'':
448
0
        if (tok->flags & JSON_TOKENER_STRICT)
449
0
        {
450
          /* in STRICT mode only double-quote are allowed */
451
0
          tok->err = json_tokener_error_parse_unexpected;
452
0
          goto out;
453
0
        }
454
        /* FALLTHRU */
455
0
      case '"':
456
0
        state = json_tokener_state_string;
457
0
        printbuf_reset(tok->pb);
458
0
        tok->quote_char = c;
459
0
        break;
460
0
      case 'T':
461
0
      case 't':
462
0
      case 'F':
463
0
      case 'f':
464
0
        state = json_tokener_state_boolean;
465
0
        printbuf_reset(tok->pb);
466
0
        tok->st_pos = 0;
467
0
        goto redo_char;
468
0
      case '0':
469
0
      case '1':
470
0
      case '2':
471
0
      case '3':
472
0
      case '4':
473
0
      case '5':
474
0
      case '6':
475
0
      case '7':
476
0
      case '8':
477
0
      case '9':
478
0
      case '-':
479
0
        state = json_tokener_state_number;
480
0
        printbuf_reset(tok->pb);
481
0
        tok->is_double = 0;
482
0
        goto redo_char;
483
0
      default: tok->err = json_tokener_error_parse_unexpected; goto out;
484
0
      }
485
0
      break;
486
487
0
    case json_tokener_state_finish:
488
0
      if (tok->depth == 0)
489
0
        goto out;
490
0
      obj = json_object_get(current);
491
0
      json_tokener_reset_level(tok, tok->depth);
492
0
      tok->depth--;
493
0
      goto redo_char;
494
495
0
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
496
0
    {
497
      /* If we were guaranteed to have len set, then we could (usually) handle
498
       * the entire "Infinity" check in a single strncmp (strncasecmp), but
499
       * since len might be -1 (i.e. "read until \0"), we need to check it
500
       * a character at a time.
501
       * Trying to handle it both ways would make this code considerably more
502
       * complicated with likely little performance benefit.
503
       */
504
0
      int is_negative = 0;
505
506
      /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
507
0
      while (tok->st_pos < (int)json_inf_str_len)
508
0
      {
509
0
        char inf_char = *str;
510
0
        if (inf_char != json_inf_str[tok->st_pos] &&
511
0
            ((tok->flags & JSON_TOKENER_STRICT) ||
512
0
              inf_char != json_inf_str_invert[tok->st_pos])
513
0
           )
514
0
        {
515
0
          tok->err = json_tokener_error_parse_unexpected;
516
0
          goto out;
517
0
        }
518
0
        tok->st_pos++;
519
0
        (void)ADVANCE_CHAR(str, tok);
520
0
        if (!PEEK_CHAR(c, tok))
521
0
        {
522
          /* out of input chars, for now at least */
523
0
          goto out;
524
0
        }
525
0
      }
526
      /* We checked the full length of "Infinity", so create the object.
527
       * When handling -Infinity, the number parsing code will have dropped
528
       * the "-" into tok->pb for us, so check it now.
529
       */
530
0
      if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
531
0
      {
532
0
        is_negative = 1;
533
0
      }
534
0
      current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
535
0
      if (current == NULL)
536
0
      {
537
0
        tok->err = json_tokener_error_memory;
538
0
        goto out;
539
0
      }
540
0
      saved_state = json_tokener_state_finish;
541
0
      state = json_tokener_state_eatws;
542
0
      goto redo_char;
543
0
    }
544
0
    break;
545
0
    case json_tokener_state_null: /* aka starts with 'n' */
546
0
    {
547
0
      int size;
548
0
      int size_nan;
549
0
      printbuf_memappend_checked(tok->pb, &c, 1);
550
0
      size = json_min(tok->st_pos + 1, json_null_str_len);
551
0
      size_nan = json_min(tok->st_pos + 1, json_nan_str_len);
552
0
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
553
0
           strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||
554
0
          (strncmp(json_null_str, tok->pb->buf, size) == 0))
555
0
      {
556
0
        if (tok->st_pos == json_null_str_len)
557
0
        {
558
0
          current = NULL;
559
0
          saved_state = json_tokener_state_finish;
560
0
          state = json_tokener_state_eatws;
561
0
          goto redo_char;
562
0
        }
563
0
      }
564
0
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
565
0
                strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
566
0
               (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))
567
0
      {
568
0
        if (tok->st_pos == json_nan_str_len)
569
0
        {
570
0
          current = json_object_new_double(NAN);
571
0
          if (current == NULL)
572
0
          {
573
0
            tok->err = json_tokener_error_memory;
574
0
            goto out;
575
0
          }
576
0
          saved_state = json_tokener_state_finish;
577
0
          state = json_tokener_state_eatws;
578
0
          goto redo_char;
579
0
        }
580
0
      }
581
0
      else
582
0
      {
583
0
        tok->err = json_tokener_error_parse_null;
584
0
        goto out;
585
0
      }
586
0
      tok->st_pos++;
587
0
    }
588
0
    break;
589
590
0
    case json_tokener_state_comment_start:
591
0
      if (c == '*')
592
0
      {
593
0
        state = json_tokener_state_comment;
594
0
      }
595
0
      else if (c == '/')
596
0
      {
597
0
        state = json_tokener_state_comment_eol;
598
0
      }
599
0
      else
600
0
      {
601
0
        tok->err = json_tokener_error_parse_comment;
602
0
        goto out;
603
0
      }
604
0
      printbuf_memappend_checked(tok->pb, &c, 1);
605
0
      break;
606
607
0
    case json_tokener_state_comment:
608
0
    {
609
      /* Advance until we change state */
610
0
      const char *case_start = str;
611
0
      while (c != '*')
612
0
      {
613
0
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
614
0
        {
615
0
          printbuf_memappend_checked(tok->pb, case_start,
616
0
                                     str - case_start);
617
0
          goto out;
618
0
        }
619
0
      }
620
0
      printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);
621
0
      state = json_tokener_state_comment_end;
622
0
    }
623
0
    break;
624
625
0
    case json_tokener_state_comment_eol:
626
0
    {
627
      /* Advance until we change state */
628
0
      const char *case_start = str;
629
0
      while (c != '\n')
630
0
      {
631
0
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
632
0
        {
633
0
          printbuf_memappend_checked(tok->pb, case_start,
634
0
                                     str - case_start);
635
0
          goto out;
636
0
        }
637
0
      }
638
0
      printbuf_memappend_checked(tok->pb, case_start, str - case_start);
639
0
      MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
640
0
      state = json_tokener_state_eatws;
641
0
    }
642
0
    break;
643
644
0
    case json_tokener_state_comment_end:
645
0
      printbuf_memappend_checked(tok->pb, &c, 1);
646
0
      if (c == '/')
647
0
      {
648
0
        MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
649
0
        state = json_tokener_state_eatws;
650
0
      }
651
0
      else
652
0
      {
653
0
        state = json_tokener_state_comment;
654
0
      }
655
0
      break;
656
657
0
    case json_tokener_state_string:
658
0
    {
659
      /* Advance until we change state */
660
0
      const char *case_start = str;
661
0
      while (1)
662
0
      {
663
0
        if (c == tok->quote_char)
664
0
        {
665
0
          printbuf_memappend_checked(tok->pb, case_start,
666
0
                                     str - case_start);
667
0
          current =
668
0
              json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
669
0
          if (current == NULL)
670
0
          {
671
0
            tok->err = json_tokener_error_memory;
672
0
            goto out;
673
0
          }
674
0
          saved_state = json_tokener_state_finish;
675
0
          state = json_tokener_state_eatws;
676
0
          break;
677
0
        }
678
0
        else if (c == '\\')
679
0
        {
680
0
          printbuf_memappend_checked(tok->pb, case_start,
681
0
                                     str - case_start);
682
0
          saved_state = json_tokener_state_string;
683
0
          state = json_tokener_state_string_escape;
684
0
          break;
685
0
        }
686
0
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
687
0
        {
688
          // Disallow control characters in strict mode
689
0
          tok->err = json_tokener_error_parse_string;
690
0
          goto out;
691
0
        }
692
0
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
693
0
        {
694
0
          printbuf_memappend_checked(tok->pb, case_start,
695
0
                                     str - case_start);
696
0
          goto out;
697
0
        }
698
0
      }
699
0
    }
700
0
    break;
701
702
0
    case json_tokener_state_string_escape:
703
0
      switch (c)
704
0
      {
705
0
      case '"':
706
0
      case '\\':
707
0
      case '/':
708
0
        printbuf_memappend_checked(tok->pb, &c, 1);
709
0
        state = saved_state;
710
0
        break;
711
0
      case 'b':
712
0
      case 'n':
713
0
      case 'r':
714
0
      case 't':
715
0
      case 'f':
716
0
        if (c == 'b')
717
0
          printbuf_memappend_checked(tok->pb, "\b", 1);
718
0
        else if (c == 'n')
719
0
          printbuf_memappend_checked(tok->pb, "\n", 1);
720
0
        else if (c == 'r')
721
0
          printbuf_memappend_checked(tok->pb, "\r", 1);
722
0
        else if (c == 't')
723
0
          printbuf_memappend_checked(tok->pb, "\t", 1);
724
0
        else if (c == 'f')
725
0
          printbuf_memappend_checked(tok->pb, "\f", 1);
726
0
        state = saved_state;
727
0
        break;
728
0
      case 'u':
729
0
        tok->ucs_char = 0;
730
0
        tok->st_pos = 0;
731
0
        state = json_tokener_state_escape_unicode;
732
0
        break;
733
0
      default: tok->err = json_tokener_error_parse_string; goto out;
734
0
      }
735
0
      break;
736
737
      // ===================================================
738
739
0
    case json_tokener_state_escape_unicode:
740
0
    {
741
      /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */
742
0
      while (1)
743
0
      {
744
0
        if (!c || !is_hex_char(c))
745
0
        {
746
0
          tok->err = json_tokener_error_parse_string;
747
0
          goto out;
748
0
        }
749
0
        tok->ucs_char |=
750
0
            ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));
751
0
        tok->st_pos++;
752
0
        if (tok->st_pos >= 4)
753
0
          break;
754
755
0
        (void)ADVANCE_CHAR(str, tok);
756
0
        if (!PEEK_CHAR(c, tok))
757
0
        {
758
          /*
759
           * We're out of characters in the current call to
760
           * json_tokener_parse(), but a subsequent call might
761
           * provide us with more, so leave our current state
762
           * as-is (including tok->high_surrogate) and return.
763
           */
764
0
          goto out;
765
0
        }
766
0
      }
767
0
      tok->st_pos = 0;
768
769
      /* Now, we have a full \uNNNN sequence in tok->ucs_char */
770
771
      /* If the *previous* sequence was a high surrogate ... */
772
0
      if (tok->high_surrogate)
773
0
      {
774
0
        if (IS_LOW_SURROGATE(tok->ucs_char))
775
0
        {
776
          /* Recalculate the ucs_char, then fall thru to process normally */
777
0
          tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,
778
0
                                                tok->ucs_char);
779
0
        }
780
0
        else
781
0
        {
782
          /* High surrogate was not followed by a low surrogate
783
           * Replace the high and process the rest normally
784
           */
785
0
          printbuf_memappend_checked(tok->pb,
786
0
                                     (char *)utf8_replacement_char, 3);
787
0
        }
788
0
        tok->high_surrogate = 0;
789
0
      }
790
791
0
      if (tok->ucs_char < 0x80)
792
0
      {
793
0
        unsigned char unescaped_utf[1];
794
0
        unescaped_utf[0] = tok->ucs_char;
795
0
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);
796
0
      }
797
0
      else if (tok->ucs_char < 0x800)
798
0
      {
799
0
        unsigned char unescaped_utf[2];
800
0
        unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
801
0
        unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
802
0
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);
803
0
      }
804
0
      else if (IS_HIGH_SURROGATE(tok->ucs_char))
805
0
      {
806
        /*
807
         * The next two characters should be \u, HOWEVER,
808
         * we can't simply peek ahead here, because the
809
         * characters we need might not be passed to us
810
         * until a subsequent call to json_tokener_parse.
811
         * Instead, transition through a couple of states.
812
         * (now):
813
         *   _escape_unicode => _unicode_need_escape
814
         * (see a '\\' char):
815
         *   _unicode_need_escape => _unicode_need_u
816
         * (see a 'u' char):
817
         *   _unicode_need_u => _escape_unicode
818
         *      ...and we'll end up back around here.
819
         */
820
0
        tok->high_surrogate = tok->ucs_char;
821
0
        tok->ucs_char = 0;
822
0
        state = json_tokener_state_escape_unicode_need_escape;
823
0
        break;
824
0
      }
825
0
      else if (IS_LOW_SURROGATE(tok->ucs_char))
826
0
      {
827
        /* Got a low surrogate not preceded by a high */
828
0
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
829
0
      }
830
0
      else if (tok->ucs_char < 0x10000)
831
0
      {
832
0
        unsigned char unescaped_utf[3];
833
0
        unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
834
0
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
835
0
        unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
836
0
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);
837
0
      }
838
0
      else if (tok->ucs_char < 0x110000)
839
0
      {
840
0
        unsigned char unescaped_utf[4];
841
0
        unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
842
0
        unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
843
0
        unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
844
0
        unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
845
0
        printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);
846
0
      }
847
0
      else
848
0
      {
849
        /* Don't know what we got--insert the replacement char */
850
0
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
851
0
      }
852
0
      state = saved_state; // i.e. _state_string or _state_object_field
853
0
    }
854
0
    break;
855
856
0
    case json_tokener_state_escape_unicode_need_escape:
857
      // We get here after processing a high_surrogate
858
      // require a '\\' char
859
0
      if (!c || c != '\\')
860
0
      {
861
        /* Got a high surrogate without another sequence following
862
         * it.  Put a replacement char in for the high surrogate
863
         * and pop back up to _state_string or _state_object_field.
864
         */
865
0
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
866
0
        tok->high_surrogate = 0;
867
0
        tok->ucs_char = 0;
868
0
        tok->st_pos = 0;
869
0
        state = saved_state;
870
0
        goto redo_char;
871
0
      }
872
0
      state = json_tokener_state_escape_unicode_need_u;
873
0
      break;
874
875
0
    case json_tokener_state_escape_unicode_need_u:
876
      /* We already had a \ char, check that it's \u */
877
0
      if (!c || c != 'u')
878
0
      {
879
        /* Got a high surrogate with some non-unicode escape
880
         * sequence following it.
881
         * Put a replacement char in for the high surrogate
882
         * and handle the escape sequence normally.
883
         */
884
0
        printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);
885
0
        tok->high_surrogate = 0;
886
0
        tok->ucs_char = 0;
887
0
        tok->st_pos = 0;
888
0
        state = json_tokener_state_string_escape;
889
0
        goto redo_char;
890
0
      }
891
0
      state = json_tokener_state_escape_unicode;
892
0
      break;
893
894
      // ===================================================
895
896
0
    case json_tokener_state_boolean:
897
0
    {
898
0
      int size1, size2;
899
0
      printbuf_memappend_checked(tok->pb, &c, 1);
900
0
      size1 = json_min(tok->st_pos + 1, json_true_str_len);
901
0
      size2 = json_min(tok->st_pos + 1, json_false_str_len);
902
0
      if ((!(tok->flags & JSON_TOKENER_STRICT) &&
903
0
           strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||
904
0
          (strncmp(json_true_str, tok->pb->buf, size1) == 0))
905
0
      {
906
0
        if (tok->st_pos == json_true_str_len)
907
0
        {
908
0
          current = json_object_new_boolean(1);
909
0
          if (current == NULL)
910
0
          {
911
0
            tok->err = json_tokener_error_memory;
912
0
            goto out;
913
0
          }
914
0
          saved_state = json_tokener_state_finish;
915
0
          state = json_tokener_state_eatws;
916
0
          goto redo_char;
917
0
        }
918
0
      }
919
0
      else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
920
0
                strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||
921
0
               (strncmp(json_false_str, tok->pb->buf, size2) == 0))
922
0
      {
923
0
        if (tok->st_pos == json_false_str_len)
924
0
        {
925
0
          current = json_object_new_boolean(0);
926
0
          if (current == NULL)
927
0
          {
928
0
            tok->err = json_tokener_error_memory;
929
0
            goto out;
930
0
          }
931
0
          saved_state = json_tokener_state_finish;
932
0
          state = json_tokener_state_eatws;
933
0
          goto redo_char;
934
0
        }
935
0
      }
936
0
      else
937
0
      {
938
0
        tok->err = json_tokener_error_parse_boolean;
939
0
        goto out;
940
0
      }
941
0
      tok->st_pos++;
942
0
    }
943
0
    break;
944
945
0
    case json_tokener_state_number:
946
0
    {
947
      /* Advance until we change state */
948
0
      const char *case_start = str;
949
0
      int case_len = 0;
950
0
      int is_exponent = 0;
951
0
      int neg_sign_ok = 1;
952
0
      int pos_sign_ok = 0;
953
0
      if (printbuf_length(tok->pb) > 0)
954
0
      {
955
        /* We don't save all state from the previous incremental parse
956
           so we need to re-generate it based on the saved string so far.
957
         */
958
0
        char *e_loc = strchr(tok->pb->buf, 'e');
959
0
        if (!e_loc)
960
0
          e_loc = strchr(tok->pb->buf, 'E');
961
0
        if (e_loc)
962
0
        {
963
0
          char *last_saved_char =
964
0
              &tok->pb->buf[printbuf_length(tok->pb) - 1];
965
0
          is_exponent = 1;
966
0
          pos_sign_ok = neg_sign_ok = 1;
967
          /* If the "e" isn't at the end, we can't start with a '-' */
968
0
          if (e_loc != last_saved_char)
969
0
          {
970
0
            neg_sign_ok = 0;
971
0
            pos_sign_ok = 0;
972
0
          }
973
          // else leave it set to 1, i.e. start of the new input
974
0
        }
975
0
      }
976
977
0
      while (c && ((c >= '0' && c <= '9') ||
978
0
                   (!is_exponent && (c == 'e' || c == 'E')) ||
979
0
                   (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||
980
0
                   (!tok->is_double && c == '.')))
981
0
      {
982
0
        pos_sign_ok = neg_sign_ok = 0;
983
0
        ++case_len;
984
985
        /* non-digit characters checks */
986
        /* note: since the main loop condition to get here was
987
         * an input starting with 0-9 or '-', we are
988
         * protected from input starting with '.' or
989
         * e/E.
990
         */
991
0
        switch (c)
992
0
        {
993
0
        case '.':
994
0
          tok->is_double = 1;
995
0
          pos_sign_ok = 1;
996
0
          neg_sign_ok = 1;
997
0
          break;
998
0
        case 'e': /* FALLTHRU */
999
0
        case 'E':
1000
0
          is_exponent = 1;
1001
0
          tok->is_double = 1;
1002
          /* the exponent part can begin with a negative sign */
1003
0
          pos_sign_ok = neg_sign_ok = 1;
1004
0
          break;
1005
0
        default: break;
1006
0
        }
1007
1008
0
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1009
0
        {
1010
0
          printbuf_memappend_checked(tok->pb, case_start, case_len);
1011
0
          goto out;
1012
0
        }
1013
0
      }
1014
      /*
1015
        Now we know c isn't a valid number char, but check whether
1016
        it might have been intended to be, and return a potentially
1017
        more understandable error right away.
1018
        However, if we're at the top-level, use the number as-is
1019
        because c can be part of a new object to parse on the
1020
        next call to json_tokener_parse().
1021
       */
1022
0
      if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&
1023
0
          c != 'I' && c != 'i' && !is_ws_char(c))
1024
0
      {
1025
0
        tok->err = json_tokener_error_parse_number;
1026
0
        goto out;
1027
0
      }
1028
0
      if (case_len > 0)
1029
0
        printbuf_memappend_checked(tok->pb, case_start, case_len);
1030
1031
      // Check for -Infinity
1032
0
      if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))
1033
0
      {
1034
0
        state = json_tokener_state_inf;
1035
0
        tok->st_pos = 0;
1036
0
        goto redo_char;
1037
0
      }
1038
0
      if (tok->flags & JSON_TOKENER_STRICT)
1039
0
      {
1040
        /* Check the accumulated text against the RFC 8259 grammar:
1041
         *
1042
         *   number = [ minus ] int [ frac ] [ exp ]
1043
         *   int    = zero / ( digit1-9 *DIGIT )
1044
         *   frac   = decimal-point 1*DIGIT
1045
         *   exp    = e [ minus / plus ] 1*DIGIT
1046
         *
1047
         * so the integer part is mandatory and may not carry a
1048
         * leading zero, and both the fraction and the exponent
1049
         * need at least one digit of their own. That rejects
1050
         * "01", ".5", "-.123", "1.", "2.e3" and "1e", while
1051
         * "0", "-0", "0.5" and "2e3" stay valid.
1052
         */
1053
0
        const char *num = tok->pb->buf;
1054
0
        if (*num == '-')
1055
0
          num++;
1056
0
        if (*num == '0')
1057
0
        {
1058
0
          num++;
1059
0
          if (*num >= '0' && *num <= '9')
1060
0
          {
1061
0
            tok->err = json_tokener_error_parse_number;
1062
0
            goto out;
1063
0
          }
1064
0
        }
1065
0
        else if (*num >= '1' && *num <= '9')
1066
0
        {
1067
0
          while (*num >= '0' && *num <= '9')
1068
0
            num++;
1069
0
        }
1070
0
        else
1071
0
        {
1072
          /* no integer part at all, e.g. ".5" or "-.123" */
1073
0
          tok->err = json_tokener_error_parse_number;
1074
0
          goto out;
1075
0
        }
1076
0
        if (*num == '.')
1077
0
        {
1078
0
          num++;
1079
0
          if (!(*num >= '0' && *num <= '9'))
1080
0
          {
1081
0
            tok->err = json_tokener_error_parse_number;
1082
0
            goto out;
1083
0
          }
1084
0
          while (*num >= '0' && *num <= '9')
1085
0
            num++;
1086
0
        }
1087
0
        if (*num == 'e' || *num == 'E')
1088
0
        {
1089
0
          num++;
1090
0
          if (*num == '+' || *num == '-')
1091
0
            num++;
1092
0
          if (!(*num >= '0' && *num <= '9'))
1093
0
          {
1094
0
            tok->err = json_tokener_error_parse_number;
1095
0
            goto out;
1096
0
          }
1097
0
          while (*num >= '0' && *num <= '9')
1098
0
            num++;
1099
0
        }
1100
0
        if (*num != '\0')
1101
0
        {
1102
0
          tok->err = json_tokener_error_parse_number;
1103
0
          goto out;
1104
0
        }
1105
0
      }
1106
0
      if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))
1107
0
      {
1108
        /* Trim some chars off the end, to allow things
1109
           like "123e+" to parse ok. */
1110
0
        while (printbuf_length(tok->pb) > 1)
1111
0
        {
1112
0
          char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];
1113
0
          if (last_char != 'e' && last_char != 'E' &&
1114
0
              last_char != '-' && last_char != '+')
1115
0
          {
1116
0
            break;
1117
0
          }
1118
0
          tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';
1119
0
          printbuf_length(tok->pb)--;
1120
0
        }
1121
0
      }
1122
0
    }
1123
0
      {
1124
0
        int64_t num64;
1125
0
        uint64_t numuint64;
1126
0
        double numd;
1127
0
        if (!tok->is_double && tok->pb->buf[0] == '-' &&
1128
0
            json_parse_int64(tok->pb->buf, &num64) == 0)
1129
0
        {
1130
0
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1131
0
          {
1132
0
            tok->err = json_tokener_error_parse_number;
1133
0
            goto out;
1134
0
          }
1135
0
          current = json_object_new_int64(num64);
1136
0
          if (current == NULL)
1137
0
          {
1138
0
            tok->err = json_tokener_error_memory;
1139
0
            goto out;
1140
0
          }
1141
0
        }
1142
0
        else if (!tok->is_double && tok->pb->buf[0] != '-' &&
1143
0
                 json_parse_uint64(tok->pb->buf, &numuint64) == 0)
1144
0
        {
1145
0
          if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))
1146
0
          {
1147
0
            tok->err = json_tokener_error_parse_number;
1148
0
            goto out;
1149
0
          }
1150
0
          if (numuint64 <= INT64_MAX)
1151
0
          {
1152
0
            num64 = (int64_t)numuint64;
1153
0
            current = json_object_new_int64(num64);
1154
0
            if (current == NULL)
1155
0
            {
1156
0
              tok->err = json_tokener_error_memory;
1157
0
              goto out;
1158
0
            }
1159
0
          }
1160
0
          else
1161
0
          {
1162
0
            current = json_object_new_uint64(numuint64);
1163
0
            if (current == NULL)
1164
0
            {
1165
0
              tok->err = json_tokener_error_memory;
1166
0
              goto out;
1167
0
            }
1168
0
          }
1169
0
        }
1170
0
        else if (tok->is_double &&
1171
0
                 json_tokener_parse_double(
1172
0
                     tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)
1173
0
        {
1174
0
          current = json_object_new_double_s(numd, tok->pb->buf);
1175
0
          if (current == NULL)
1176
0
          {
1177
0
            tok->err = json_tokener_error_memory;
1178
0
            goto out;
1179
0
          }
1180
0
        }
1181
0
        else
1182
0
        {
1183
0
          tok->err = json_tokener_error_parse_number;
1184
0
          goto out;
1185
0
        }
1186
0
        saved_state = json_tokener_state_finish;
1187
0
        state = json_tokener_state_eatws;
1188
0
        goto redo_char;
1189
0
      }
1190
0
      break;
1191
1192
0
    case json_tokener_state_array_after_sep:
1193
0
    case json_tokener_state_array:
1194
0
      if (c == ']')
1195
0
      {
1196
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1197
0
        json_object_array_shrink(current, 0);
1198
1199
0
        if (state == json_tokener_state_array_after_sep &&
1200
0
            (tok->flags & JSON_TOKENER_STRICT))
1201
0
        {
1202
0
          tok->err = json_tokener_error_parse_unexpected;
1203
0
          goto out;
1204
0
        }
1205
0
        saved_state = json_tokener_state_finish;
1206
0
        state = json_tokener_state_eatws;
1207
0
      }
1208
0
      else
1209
0
      {
1210
0
        if (tok->depth >= tok->max_depth - 1)
1211
0
        {
1212
0
          tok->err = json_tokener_error_depth;
1213
0
          goto out;
1214
0
        }
1215
0
        state = json_tokener_state_array_add;
1216
0
        tok->depth++;
1217
0
        json_tokener_reset_level(tok, tok->depth);
1218
0
        goto redo_char;
1219
0
      }
1220
0
      break;
1221
1222
0
    case json_tokener_state_array_add:
1223
0
      if (json_object_array_add(current, obj) != 0)
1224
0
      {
1225
0
        tok->err = json_tokener_error_memory;
1226
0
        goto out;
1227
0
      }
1228
0
      saved_state = json_tokener_state_array_sep;
1229
0
      state = json_tokener_state_eatws;
1230
0
      goto redo_char;
1231
1232
0
    case json_tokener_state_array_sep:
1233
0
      if (c == ']')
1234
0
      {
1235
        // Minimize memory usage; assume parsed objs are unlikely to be changed
1236
0
        json_object_array_shrink(current, 0);
1237
1238
0
        saved_state = json_tokener_state_finish;
1239
0
        state = json_tokener_state_eatws;
1240
0
      }
1241
0
      else if (c == ',')
1242
0
      {
1243
0
        saved_state = json_tokener_state_array_after_sep;
1244
0
        state = json_tokener_state_eatws;
1245
0
      }
1246
0
      else
1247
0
      {
1248
0
        tok->err = json_tokener_error_parse_array;
1249
0
        goto out;
1250
0
      }
1251
0
      break;
1252
1253
0
    case json_tokener_state_object_field_start:
1254
0
    case json_tokener_state_object_field_start_after_sep:
1255
0
      if (c == '}')
1256
0
      {
1257
0
        if (state == json_tokener_state_object_field_start_after_sep &&
1258
0
            (tok->flags & JSON_TOKENER_STRICT))
1259
0
        {
1260
0
          tok->err = json_tokener_error_parse_unexpected;
1261
0
          goto out;
1262
0
        }
1263
0
        saved_state = json_tokener_state_finish;
1264
0
        state = json_tokener_state_eatws;
1265
0
      }
1266
0
      else if (c == '"' || c == '\'')
1267
0
      {
1268
0
        tok->quote_char = c;
1269
0
        printbuf_reset(tok->pb);
1270
0
        state = json_tokener_state_object_field;
1271
0
      }
1272
0
      else
1273
0
      {
1274
0
        tok->err = json_tokener_error_parse_object_key_name;
1275
0
        goto out;
1276
0
      }
1277
0
      break;
1278
1279
0
    case json_tokener_state_object_field:
1280
0
    {
1281
      /* Advance until we change state */
1282
0
      const char *case_start = str;
1283
0
      while (1)
1284
0
      {
1285
0
        if (c == tok->quote_char)
1286
0
        {
1287
0
          printbuf_memappend_checked(tok->pb, case_start,
1288
0
                                     str - case_start);
1289
0
          obj_field_name = strdup(tok->pb->buf);
1290
0
          if (obj_field_name == NULL)
1291
0
          {
1292
0
            tok->err = json_tokener_error_memory;
1293
0
            goto out;
1294
0
          }
1295
0
          saved_state = json_tokener_state_object_field_end;
1296
0
          state = json_tokener_state_eatws;
1297
0
          break;
1298
0
        }
1299
0
        else if (c == '\\')
1300
0
        {
1301
0
          printbuf_memappend_checked(tok->pb, case_start,
1302
0
                                     str - case_start);
1303
0
          saved_state = json_tokener_state_object_field;
1304
0
          state = json_tokener_state_string_escape;
1305
0
          break;
1306
0
        }
1307
0
        else if ((tok->flags & JSON_TOKENER_STRICT) && (unsigned char)c <= 0x1f)
1308
0
        {
1309
          // Disallow control characters in strict mode
1310
0
          tok->err = json_tokener_error_parse_string;
1311
0
          goto out;
1312
0
        }
1313
0
        if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))
1314
0
        {
1315
0
          printbuf_memappend_checked(tok->pb, case_start,
1316
0
                                     str - case_start);
1317
0
          goto out;
1318
0
        }
1319
0
      }
1320
0
    }
1321
0
    break;
1322
1323
0
    case json_tokener_state_object_field_end:
1324
0
      if (c == ':')
1325
0
      {
1326
0
        saved_state = json_tokener_state_object_value;
1327
0
        state = json_tokener_state_eatws;
1328
0
      }
1329
0
      else
1330
0
      {
1331
0
        tok->err = json_tokener_error_parse_object_key_sep;
1332
0
        goto out;
1333
0
      }
1334
0
      break;
1335
1336
0
    case json_tokener_state_object_value:
1337
0
      if (tok->depth >= tok->max_depth - 1)
1338
0
      {
1339
0
        tok->err = json_tokener_error_depth;
1340
0
        goto out;
1341
0
      }
1342
0
      state = json_tokener_state_object_value_add;
1343
0
      tok->depth++;
1344
0
      json_tokener_reset_level(tok, tok->depth);
1345
0
      goto redo_char;
1346
1347
0
    case json_tokener_state_object_value_add:
1348
0
      if (json_object_object_add(current, obj_field_name, obj) != 0)
1349
0
      {
1350
0
        tok->err = json_tokener_error_memory;
1351
0
        goto out;
1352
0
      }
1353
0
      free(obj_field_name);
1354
0
      obj_field_name = NULL;
1355
0
      saved_state = json_tokener_state_object_sep;
1356
0
      state = json_tokener_state_eatws;
1357
0
      goto redo_char;
1358
1359
0
    case json_tokener_state_object_sep:
1360
      /* { */
1361
0
      if (c == '}')
1362
0
      {
1363
0
        saved_state = json_tokener_state_finish;
1364
0
        state = json_tokener_state_eatws;
1365
0
      }
1366
0
      else if (c == ',')
1367
0
      {
1368
0
        saved_state = json_tokener_state_object_field_start_after_sep;
1369
0
        state = json_tokener_state_eatws;
1370
0
      }
1371
0
      else
1372
0
      {
1373
0
        tok->err = json_tokener_error_parse_object_value_sep;
1374
0
        goto out;
1375
0
      }
1376
0
      break;
1377
0
    }
1378
0
    (void)ADVANCE_CHAR(str, tok);
1379
0
    if (!c) // This is the char *before* advancing
1380
0
      break;
1381
0
  } /* while(PEEK_CHAR) */
1382
1383
0
out:
1384
0
  if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))
1385
0
  {
1386
0
    tok->err = json_tokener_error_parse_utf8_string;
1387
0
  }
1388
0
  if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&
1389
0
      (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==
1390
0
          JSON_TOKENER_STRICT)
1391
0
  {
1392
    /* unexpected char after JSON data */
1393
0
    tok->err = json_tokener_error_parse_unexpected;
1394
0
  }
1395
0
  if (!c)
1396
0
  {
1397
    /* We hit an eof char (0) */
1398
0
    if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)
1399
0
      tok->err = json_tokener_error_parse_eof;
1400
0
  }
1401
1402
0
#ifdef HAVE_USELOCALE
1403
0
  uselocale(oldlocale);
1404
#elif defined(HAVE_SETLOCALE)
1405
  setlocale(LC_NUMERIC, oldlocale);
1406
  free(oldlocale);
1407
#endif
1408
1409
0
  if (tok->err == json_tokener_success)
1410
0
  {
1411
0
    json_object *ret = json_object_get(current);
1412
0
    int ii;
1413
1414
    /* Partially reset, so we parse additional objects on subsequent calls. */
1415
0
    for (ii = tok->depth; ii >= 0; ii--)
1416
0
      json_tokener_reset_level(tok, ii);
1417
0
    return ret;
1418
0
  }
1419
1420
0
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err],
1421
0
           tok->char_offset);
1422
0
  return NULL;
1423
0
}
1424
1425
static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes)
1426
0
{
1427
0
  unsigned char chr = c;
1428
0
  if (*nBytes == 0)
1429
0
  {
1430
0
    if (chr >= 0x80)
1431
0
    {
1432
0
      if ((chr & 0xe0) == 0xc0)
1433
0
        *nBytes = 1;
1434
0
      else if ((chr & 0xf0) == 0xe0)
1435
0
        *nBytes = 2;
1436
0
      else if ((chr & 0xf8) == 0xf0)
1437
0
        *nBytes = 3;
1438
0
      else
1439
0
        return 0;
1440
0
    }
1441
0
  }
1442
0
  else
1443
0
  {
1444
0
    if ((chr & 0xC0) != 0x80)
1445
0
      return 0;
1446
0
    (*nBytes)--;
1447
0
  }
1448
0
  return 1;
1449
0
}
1450
1451
void json_tokener_set_flags(struct json_tokener *tok, int flags)
1452
0
{
1453
0
  tok->flags = flags;
1454
0
}
1455
1456
size_t json_tokener_get_parse_end(struct json_tokener *tok)
1457
0
{
1458
0
  assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */
1459
0
  return (size_t)tok->char_offset;
1460
0
}
1461
1462
static int json_tokener_parse_double(const char *buf, int len, double *retval)
1463
0
{
1464
0
  char *end;
1465
0
  *retval = strtod(buf, &end);
1466
0
  if (buf + len == end)
1467
0
    return 0; // It worked
1468
0
  return 1;
1469
0
}
1470
1471
#ifdef HAVE_USELOCALE
1472
/* Release the static C-numeric locale when the library is unloaded.
1473
 * This keeps Valgrind clean.
1474
 */
1475
#if defined(__GNUC__) || defined(__clang__)
1476
#define JSON_TOKENER_DESTRUCTOR __attribute__((destructor))
1477
#elif defined(_WIN32) || defined(_WIN64)
1478
#include <windows.h>
1479
1480
// Windows implementation using DllMain
1481
// Executed when FreeLibrary is called or the process exits
1482
#define JSON_TOKENER_DESTRUCTOR \
1483
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) \
1484
{ \
1485
  if (ul_reason_for_call == DLL_PROCESS_DETACH) \
1486
  { \
1487
    json_tokener_locale_fini(); \
1488
  } \
1489
  return TRUE; \
1490
}
1491
#endif
1492
1493
#ifdef JSON_TOKENER_DESTRUCTOR
1494
JSON_TOKENER_DESTRUCTOR
1495
static void json_tokener_locale_fini(void)
1496
0
{
1497
0
  if (c_numeric_locale != (locale_t)0)
1498
0
  {
1499
0
    freelocale(c_numeric_locale);
1500
0
    c_numeric_locale = (locale_t)0;
1501
0
  }
1502
0
}
1503
#endif
1504
1505
#endif /* HAVE_USELOCALE */