/src/json-c/json_tokener.c
Line  | Count  | Source (jump to first uncovered line)  | 
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  | 27.7k  | #define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x)&7) + 9)  | 
48  |  |  | 
49  |  | #if !HAVE_STRNCASECMP && defined(_MSC_VER)  | 
50  |  | /* MSC has the version as _strnicmp */  | 
51  |  | #define strncasecmp _strnicmp  | 
52  |  | #elif !HAVE_STRNCASECMP  | 
53  |  | #error You do not have strncasecmp on your system.  | 
54  |  | #endif /* HAVE_STRNCASECMP */  | 
55  |  |  | 
56  |  | #if defined(_MSC_VER) && (_MSC_VER <= 1800)  | 
57  |  | /* VS2013 doesn't know about "inline" */  | 
58  |  | #define inline __inline  | 
59  |  | #elif defined(AIX_CC)  | 
60  |  | #define inline  | 
61  |  | #endif  | 
62  |  |  | 
63  |  | /* The following helper functions are used to speed up parsing. They  | 
64  |  |  * are faster than their ctype counterparts because they assume that  | 
65  |  |  * the input is in ASCII and that the locale is set to "C". The  | 
66  |  |  * compiler will also inline these functions, providing an additional  | 
67  |  |  * speedup by saving on function calls.  | 
68  |  |  */  | 
69  |  | static inline int is_ws_char(char c)  | 
70  | 1.99M  | { | 
71  | 1.99M  |   return c == ' '  | 
72  | 1.99M  |       || c == '\t'  | 
73  | 1.99M  |       || c == '\n'  | 
74  | 1.99M  |       || c == '\r';  | 
75  | 1.99M  | }  | 
76  |  |  | 
77  |  | static inline int is_hex_char(char c)  | 
78  | 27.7k  | { | 
79  | 27.7k  |   return (c >= '0' && c <= '9')  | 
80  | 27.7k  |       || (c >= 'A' && c <= 'F')  | 
81  | 27.7k  |       || (c >= 'a' && c <= 'f');  | 
82  | 27.7k  | }  | 
83  |  |  | 
84  |  | /* Use C99 NAN by default; if not available, nan("") should work too. */ | 
85  |  | #ifndef NAN  | 
86  |  | #define NAN nan("") | 
87  |  | #endif /* !NAN */  | 
88  |  |  | 
89  |  | static const char json_null_str[] = "null";  | 
90  |  | static const int json_null_str_len = sizeof(json_null_str) - 1;  | 
91  |  | static const char json_inf_str[] = "Infinity";  | 
92  |  | /* Swapped case "Infinity" to avoid need to call tolower() on input chars: */  | 
93  |  | static const char json_inf_str_invert[] = "iNFINITY";  | 
94  |  | static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;  | 
95  |  | static const char json_nan_str[] = "NaN";  | 
96  |  | static const int json_nan_str_len = sizeof(json_nan_str) - 1;  | 
97  |  | static const char json_true_str[] = "true";  | 
98  |  | static const int json_true_str_len = sizeof(json_true_str) - 1;  | 
99  |  | static const char json_false_str[] = "false";  | 
100  |  | static const int json_false_str_len = sizeof(json_false_str) - 1;  | 
101  |  |  | 
102  |  | /* clang-format off */  | 
103  |  | static const char *json_tokener_errors[] = { | 
104  |  |   "success",  | 
105  |  |   "continue",  | 
106  |  |   "nesting too deep",  | 
107  |  |   "unexpected end of data",  | 
108  |  |   "unexpected character",  | 
109  |  |   "null expected",  | 
110  |  |   "boolean expected",  | 
111  |  |   "number expected",  | 
112  |  |   "array value separator ',' expected",  | 
113  |  |   "quoted object property name expected",  | 
114  |  |   "object property name separator ':' expected",  | 
115  |  |   "object value separator ',' expected",  | 
116  |  |   "invalid string sequence",  | 
117  |  |   "expected comment",  | 
118  |  |   "invalid utf-8 string",  | 
119  |  |   "buffer size overflow",  | 
120  |  |   "out of memory"  | 
121  |  | };  | 
122  |  | /* clang-format on */  | 
123  |  |  | 
124  |  | /**  | 
125  |  |  * validete the utf-8 string in strict model.  | 
126  |  |  * if not utf-8 format, return err.  | 
127  |  |  */  | 
128  |  | static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes);  | 
129  |  |  | 
130  |  | static int json_tokener_parse_double(const char *buf, int len, double *retval);  | 
131  |  |  | 
132  |  | const char *json_tokener_error_desc(enum json_tokener_error jerr)  | 
133  | 2.45k  | { | 
134  | 2.45k  |   int jerr_int = (int)jerr;  | 
135  | 2.45k  |   if (jerr_int < 0 ||  | 
136  | 2.45k  |       jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))  | 
137  | 0  |     return "Unknown error, "  | 
138  | 0  |            "invalid json_tokener_error value passed to json_tokener_error_desc()";  | 
139  | 2.45k  |   return json_tokener_errors[jerr];  | 
140  | 2.45k  | }  | 
141  |  |  | 
142  |  | enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)  | 
143  | 4.91k  | { | 
144  | 4.91k  |   return tok->err;  | 
145  | 4.91k  | }  | 
146  |  |  | 
147  |  | /* Stuff for decoding unicode sequences */  | 
148  | 5.04k  | #define IS_HIGH_SURROGATE(uc) (((uc)&0xFC00) == 0xD800)  | 
149  | 3.78k  | #define IS_LOW_SURROGATE(uc) (((uc)&0xFC00) == 0xDC00)  | 
150  | 843  | #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  | 11.0k  | { | 
155  | 11.0k  |   struct json_tokener *tok;  | 
156  |  |  | 
157  | 11.0k  |   if (depth < 1)  | 
158  | 0  |     return NULL;  | 
159  |  |  | 
160  | 11.0k  |   tok = (struct json_tokener *)calloc(1, sizeof(struct json_tokener));  | 
161  | 11.0k  |   if (!tok)  | 
162  | 0  |     return NULL;  | 
163  | 11.0k  |   tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));  | 
164  | 11.0k  |   if (!tok->stack)  | 
165  | 0  |   { | 
166  | 0  |     free(tok);  | 
167  | 0  |     return NULL;  | 
168  | 0  |   }  | 
169  | 11.0k  |   tok->pb = printbuf_new();  | 
170  | 11.0k  |   if (!tok->pb)  | 
171  | 0  |   { | 
172  | 0  |     free(tok->stack);  | 
173  | 0  |     free(tok);  | 
174  | 0  |     return NULL;  | 
175  | 0  |   }  | 
176  | 11.0k  |   tok->max_depth = depth;  | 
177  | 11.0k  |   json_tokener_reset(tok);  | 
178  | 11.0k  |   return tok;  | 
179  | 11.0k  | }  | 
180  |  |  | 
181  |  | struct json_tokener *json_tokener_new(void)  | 
182  | 11.0k  | { | 
183  | 11.0k  |   return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);  | 
184  | 11.0k  | }  | 
185  |  |  | 
186  |  | void json_tokener_free(struct json_tokener *tok)  | 
187  | 11.0k  | { | 
188  | 11.0k  |   if (!tok)  | 
189  | 0  |     return;  | 
190  | 11.0k  |   json_tokener_reset(tok);  | 
191  | 11.0k  |   if (tok->pb)  | 
192  | 11.0k  |     printbuf_free(tok->pb);  | 
193  | 11.0k  |   free(tok->stack);  | 
194  | 11.0k  |   free(tok);  | 
195  | 11.0k  | }  | 
196  |  |  | 
197  |  | static void json_tokener_reset_level(struct json_tokener *tok, int depth)  | 
198  | 761k  | { | 
199  | 761k  |   tok->stack[depth].state = json_tokener_state_eatws;  | 
200  | 761k  |   tok->stack[depth].saved_state = json_tokener_state_start;  | 
201  | 761k  |   json_object_put(tok->stack[depth].current);  | 
202  | 761k  |   tok->stack[depth].current = NULL;  | 
203  | 761k  |   free(tok->stack[depth].obj_field_name);  | 
204  | 761k  |   tok->stack[depth].obj_field_name = NULL;  | 
205  | 761k  | }  | 
206  |  |  | 
207  |  | void json_tokener_reset(struct json_tokener *tok)  | 
208  | 22.0k  | { | 
209  | 22.0k  |   int i;  | 
210  | 22.0k  |   if (!tok)  | 
211  | 0  |     return;  | 
212  |  |  | 
213  | 47.9k  |   for (i = tok->depth; i >= 0; i--)  | 
214  | 25.9k  |     json_tokener_reset_level(tok, i);  | 
215  | 22.0k  |   tok->depth = 0;  | 
216  | 22.0k  |   tok->err = json_tokener_success;  | 
217  | 22.0k  | }  | 
218  |  |  | 
219  |  | struct json_object *json_tokener_parse(const char *str)  | 
220  | 0  | { | 
221  | 0  |   enum json_tokener_error jerr_ignored;  | 
222  | 0  |   struct json_object *obj;  | 
223  | 0  |   obj = json_tokener_parse_verbose(str, &jerr_ignored);  | 
224  | 0  |   return obj;  | 
225  | 0  | }  | 
226  |  |  | 
227  |  | struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)  | 
228  | 0  | { | 
229  | 0  |   struct json_tokener *tok;  | 
230  | 0  |   struct json_object *obj;  | 
231  |  | 
  | 
232  | 0  |   tok = json_tokener_new();  | 
233  | 0  |   if (!tok)  | 
234  | 0  |   { | 
235  | 0  |     *error = json_tokener_error_memory;  | 
236  | 0  |     return NULL;  | 
237  | 0  |   }  | 
238  | 0  |   obj = json_tokener_parse_ex(tok, str, -1);  | 
239  | 0  |   *error = tok->err;  | 
240  | 0  |   if (tok->err != json_tokener_success  | 
241  |  | #if 0  | 
242  |  |     /* This would be a more sensible default, and cause parsing  | 
243  |  |      * things like "null123" to fail when the caller can't know  | 
244  |  |      * where the parsing left off, but starting to fail would  | 
245  |  |      * be a notable behaviour change.  Save for a 1.0 release.  | 
246  |  |      */  | 
247  |  |       || json_tokener_get_parse_end(tok) != strlen(str)  | 
248  |  | #endif  | 
249  | 0  |   )  | 
250  |  |  | 
251  | 0  |   { | 
252  | 0  |     if (obj != NULL)  | 
253  | 0  |       json_object_put(obj);  | 
254  | 0  |     obj = NULL;  | 
255  | 0  |   }  | 
256  |  | 
  | 
257  | 0  |   json_tokener_free(tok);  | 
258  | 0  |   return obj;  | 
259  | 0  | }  | 
260  |  |  | 
261  | 8.82M  | #define state tok->stack[tok->depth].state  | 
262  | 3.34M  | #define saved_state tok->stack[tok->depth].saved_state  | 
263  | 1.48M  | #define current tok->stack[tok->depth].current  | 
264  | 709k  | #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  | 7.22M  |   (((tok)->char_offset == len)                                         \  | 
286  | 7.22M  |        ? (((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  | 7.22M  |        : (((tok->flags & JSON_TOKENER_VALIDATE_UTF8) &&                \  | 
291  | 7.22M  |            (!json_tokener_validate_utf8(*str, nBytesp)))               \  | 
292  | 7.22M  |               ? ((tok->err = json_tokener_error_parse_utf8_string), 0) \  | 
293  | 7.22M  |               : (((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  | 12.8M  | #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  | 666k  |   do {                                                  \ | 
308  | 666k  |     if (printbuf_memappend((p), (s), (l)) < 0)    \  | 
309  | 666k  |     {                                             \ | 
310  | 0  |       tok->err = json_tokener_error_memory; \  | 
311  | 0  |       goto out;                             \  | 
312  | 0  |     }                                             \  | 
313  | 666k  |   } 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  | 11.0k  | { | 
319  | 11.0k  |   struct json_object *obj = NULL;  | 
320  | 11.0k  |   char c = '\1';  | 
321  | 11.0k  |   unsigned int nBytes = 0;  | 
322  | 11.0k  |   unsigned int *nBytesp = &nBytes;  | 
323  |  |  | 
324  | 11.0k  | #ifdef HAVE_USELOCALE  | 
325  | 11.0k  |   locale_t oldlocale = uselocale(NULL);  | 
326  | 11.0k  |   locale_t newloc;  | 
327  |  | #elif defined(HAVE_SETLOCALE)  | 
328  |  |   char *oldlocale = NULL;  | 
329  |  | #endif  | 
330  |  |  | 
331  | 11.0k  |   tok->char_offset = 0;  | 
332  | 11.0k  |   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  | 11.0k  |   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  | 11.0k  | #ifdef HAVE_USELOCALE  | 
347  | 11.0k  |   { | 
348  | 11.0k  | #ifdef HAVE_DUPLOCALE  | 
349  | 11.0k  |     locale_t duploc = duplocale(oldlocale);  | 
350  | 11.0k  |     if (duploc == NULL && errno == ENOMEM)  | 
351  | 0  |     { | 
352  | 0  |       tok->err = json_tokener_error_memory;  | 
353  | 0  |       return NULL;  | 
354  | 0  |     }  | 
355  | 11.0k  |     newloc = newlocale(LC_NUMERIC_MASK, "C", duploc);  | 
356  |  | #else  | 
357  |  |     newloc = newlocale(LC_NUMERIC_MASK, "C", oldlocale);  | 
358  |  | #endif  | 
359  | 11.0k  |     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  | 11.0k  |     uselocale(newloc);  | 
375  | 11.0k  |   }  | 
376  |  | #elif defined(HAVE_SETLOCALE)  | 
377  |  |   { | 
378  |  |     char *tmplocale;  | 
379  |  |     tmplocale = setlocale(LC_NUMERIC, NULL);  | 
380  |  |     if (tmplocale)  | 
381  |  |     { | 
382  |  |       oldlocale = strdup(tmplocale);  | 
383  |  |       if (oldlocale == NULL)  | 
384  |  |       { | 
385  |  |         tok->err = json_tokener_error_memory;  | 
386  |  |         return NULL;  | 
387  |  |       }  | 
388  |  |     }  | 
389  |  |     setlocale(LC_NUMERIC, "C");  | 
390  |  |   }  | 
391  |  | #endif  | 
392  |  |  | 
393  | 1.32M  |   while (PEEK_CHAR(c, tok)) // Note: c might be '\0' !  | 
394  | 1.32M  |   { | 
395  |  |  | 
396  | 4.60M  |   redo_char:  | 
397  | 4.60M  |     switch (state)  | 
398  | 4.60M  |     { | 
399  |  |  | 
400  | 1.78M  |     case json_tokener_state_eatws:  | 
401  |  |       /* Advance until we change state */  | 
402  | 1.99M  |       while (is_ws_char(c))  | 
403  | 205k  |       { | 
404  | 205k  |         if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))  | 
405  | 0  |           goto out;  | 
406  | 205k  |       }  | 
407  | 1.78M  |       if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT))  | 
408  | 3.05k  |       { | 
409  | 3.05k  |         printbuf_reset(tok->pb);  | 
410  | 3.05k  |         printbuf_memappend_checked(tok->pb, &c, 1);  | 
411  | 3.05k  |         state = json_tokener_state_comment_start;  | 
412  | 3.05k  |       }  | 
413  | 1.78M  |       else  | 
414  | 1.78M  |       { | 
415  | 1.78M  |         state = saved_state;  | 
416  | 1.78M  |         goto redo_char;  | 
417  | 1.78M  |       }  | 
418  | 3.05k  |       break;  | 
419  |  |  | 
420  | 376k  |     case json_tokener_state_start:  | 
421  | 376k  |       switch (c)  | 
422  | 376k  |       { | 
423  | 62.2k  |       case '{': | 
424  | 62.2k  |         state = json_tokener_state_eatws;  | 
425  | 62.2k  |         saved_state = json_tokener_state_object_field_start;  | 
426  | 62.2k  |         current = json_object_new_object();  | 
427  | 62.2k  |         if (current == NULL)  | 
428  | 0  |         { | 
429  | 0  |           tok->err = json_tokener_error_memory;  | 
430  | 0  |           goto out;  | 
431  | 0  |         }  | 
432  | 62.2k  |         break;  | 
433  | 62.2k  |       case '[':  | 
434  | 16.7k  |         state = json_tokener_state_eatws;  | 
435  | 16.7k  |         saved_state = json_tokener_state_array;  | 
436  | 16.7k  |         current = json_object_new_array();  | 
437  | 16.7k  |         if (current == NULL)  | 
438  | 0  |         { | 
439  | 0  |           tok->err = json_tokener_error_memory;  | 
440  | 0  |           goto out;  | 
441  | 0  |         }  | 
442  | 16.7k  |         break;  | 
443  | 16.7k  |       case 'I':  | 
444  | 601  |       case 'i':  | 
445  | 601  |         state = json_tokener_state_inf;  | 
446  | 601  |         printbuf_reset(tok->pb);  | 
447  | 601  |         tok->st_pos = 0;  | 
448  | 601  |         goto redo_char;  | 
449  | 1.19k  |       case 'N':  | 
450  | 13.6k  |       case 'n':  | 
451  | 13.6k  |         state = json_tokener_state_null; // or NaN  | 
452  | 13.6k  |         printbuf_reset(tok->pb);  | 
453  | 13.6k  |         tok->st_pos = 0;  | 
454  | 13.6k  |         goto redo_char;  | 
455  | 536  |       case '\'':  | 
456  | 536  |         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  | 91.2k  |       case '"':  | 
464  | 91.2k  |         state = json_tokener_state_string;  | 
465  | 91.2k  |         printbuf_reset(tok->pb);  | 
466  | 91.2k  |         tok->quote_char = c;  | 
467  | 91.2k  |         break;  | 
468  | 613  |       case 'T':  | 
469  | 1.14k  |       case 't':  | 
470  | 1.30k  |       case 'F':  | 
471  | 1.77k  |       case 'f':  | 
472  | 1.77k  |         state = json_tokener_state_boolean;  | 
473  | 1.77k  |         printbuf_reset(tok->pb);  | 
474  | 1.77k  |         tok->st_pos = 0;  | 
475  | 1.77k  |         goto redo_char;  | 
476  | 31.6k  |       case '0':  | 
477  | 37.0k  |       case '1':  | 
478  | 41.7k  |       case '2':  | 
479  | 43.0k  |       case '3':  | 
480  | 46.6k  |       case '4':  | 
481  | 182k  |       case '5':  | 
482  | 183k  |       case '6':  | 
483  | 184k  |       case '7':  | 
484  | 185k  |       case '8':  | 
485  | 186k  |       case '9':  | 
486  | 189k  |       case '-':  | 
487  | 189k  |         state = json_tokener_state_number;  | 
488  | 189k  |         printbuf_reset(tok->pb);  | 
489  | 189k  |         tok->is_double = 0;  | 
490  | 189k  |         goto redo_char;  | 
491  | 146  |       default: tok->err = json_tokener_error_parse_unexpected; goto out;  | 
492  | 376k  |       }  | 
493  | 170k  |       break;  | 
494  |  |  | 
495  | 369k  |     case json_tokener_state_finish:  | 
496  | 369k  |       if (tok->depth == 0)  | 
497  | 8.47k  |         goto out;  | 
498  | 361k  |       obj = json_object_get(current);  | 
499  | 361k  |       json_tokener_reset_level(tok, tok->depth);  | 
500  | 361k  |       tok->depth--;  | 
501  | 361k  |       goto redo_char;  | 
502  |  |  | 
503  | 1.08k  |     case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */  | 
504  | 1.08k  |     { | 
505  |  |       /* If we were guaranteed to have len set, then we could (usually) handle  | 
506  |  |        * the entire "Infinity" check in a single strncmp (strncasecmp), but  | 
507  |  |        * since len might be -1 (i.e. "read until \0"), we need to check it  | 
508  |  |        * a character at a time.  | 
509  |  |        * Trying to handle it both ways would make this code considerably more  | 
510  |  |        * complicated with likely little performance benefit.  | 
511  |  |        */  | 
512  | 1.08k  |       int is_negative = 0;  | 
513  |  |  | 
514  |  |       /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */  | 
515  | 9.08k  |       while (tok->st_pos < (int)json_inf_str_len)  | 
516  | 8.10k  |       { | 
517  | 8.10k  |         char inf_char = *str;  | 
518  | 8.10k  |         if (inf_char != json_inf_str[tok->st_pos] &&  | 
519  | 8.10k  |             ((tok->flags & JSON_TOKENER_STRICT) ||  | 
520  | 3.53k  |               inf_char != json_inf_str_invert[tok->st_pos])  | 
521  | 8.10k  |            )  | 
522  | 110  |         { | 
523  | 110  |           tok->err = json_tokener_error_parse_unexpected;  | 
524  | 110  |           goto out;  | 
525  | 110  |         }  | 
526  | 7.99k  |         tok->st_pos++;  | 
527  | 7.99k  |         (void)ADVANCE_CHAR(str, tok);  | 
528  | 7.99k  |         if (!PEEK_CHAR(c, tok))  | 
529  | 0  |         { | 
530  |  |           /* out of input chars, for now at least */  | 
531  | 0  |           goto out;  | 
532  | 0  |         }  | 
533  | 7.99k  |       }  | 
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  | 974  |       if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')  | 
539  | 455  |       { | 
540  | 455  |         is_negative = 1;  | 
541  | 455  |       }  | 
542  | 974  |       current = json_object_new_double(is_negative ? -INFINITY : INFINITY);  | 
543  | 974  |       if (current == NULL)  | 
544  | 0  |       { | 
545  | 0  |         tok->err = json_tokener_error_memory;  | 
546  | 0  |         goto out;  | 
547  | 0  |       }  | 
548  | 974  |       saved_state = json_tokener_state_finish;  | 
549  | 974  |       state = json_tokener_state_eatws;  | 
550  | 974  |       goto redo_char;  | 
551  | 974  |     }  | 
552  | 0  |     break;  | 
553  | 67.5k  |     case json_tokener_state_null: /* aka starts with 'n' */  | 
554  | 67.5k  |     { | 
555  | 67.5k  |       int size;  | 
556  | 67.5k  |       int size_nan;  | 
557  | 67.5k  |       printbuf_memappend_checked(tok->pb, &c, 1);  | 
558  | 67.5k  |       size = json_min(tok->st_pos + 1, json_null_str_len);  | 
559  | 67.5k  |       size_nan = json_min(tok->st_pos + 1, json_nan_str_len);  | 
560  | 67.5k  |       if ((!(tok->flags & JSON_TOKENER_STRICT) &&  | 
561  | 67.5k  |            strncasecmp(json_null_str, tok->pb->buf, size) == 0) ||  | 
562  | 67.5k  |           (strncmp(json_null_str, tok->pb->buf, size) == 0))  | 
563  | 65.8k  |       { | 
564  | 65.8k  |         if (tok->st_pos == json_null_str_len)  | 
565  | 13.0k  |         { | 
566  | 13.0k  |           current = NULL;  | 
567  | 13.0k  |           saved_state = json_tokener_state_finish;  | 
568  | 13.0k  |           state = json_tokener_state_eatws;  | 
569  | 13.0k  |           goto redo_char;  | 
570  | 13.0k  |         }  | 
571  | 65.8k  |       }  | 
572  | 1.72k  |       else if ((!(tok->flags & JSON_TOKENER_STRICT) &&  | 
573  | 1.72k  |                 strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||  | 
574  | 1.72k  |                (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0))  | 
575  | 1.61k  |       { | 
576  | 1.61k  |         if (tok->st_pos == json_nan_str_len)  | 
577  | 532  |         { | 
578  | 532  |           current = json_object_new_double(NAN);  | 
579  | 532  |           if (current == NULL)  | 
580  | 0  |           { | 
581  | 0  |             tok->err = json_tokener_error_memory;  | 
582  | 0  |             goto out;  | 
583  | 0  |           }  | 
584  | 532  |           saved_state = json_tokener_state_finish;  | 
585  | 532  |           state = json_tokener_state_eatws;  | 
586  | 532  |           goto redo_char;  | 
587  | 532  |         }  | 
588  | 1.61k  |       }  | 
589  | 106  |       else  | 
590  | 106  |       { | 
591  | 106  |         tok->err = json_tokener_error_parse_null;  | 
592  | 106  |         goto out;  | 
593  | 106  |       }  | 
594  | 53.8k  |       tok->st_pos++;  | 
595  | 53.8k  |     }  | 
596  | 0  |     break;  | 
597  |  |  | 
598  | 3.05k  |     case json_tokener_state_comment_start:  | 
599  | 3.05k  |       if (c == '*')  | 
600  | 744  |       { | 
601  | 744  |         state = json_tokener_state_comment;  | 
602  | 744  |       }  | 
603  | 2.31k  |       else if (c == '/')  | 
604  | 2.21k  |       { | 
605  | 2.21k  |         state = json_tokener_state_comment_eol;  | 
606  | 2.21k  |       }  | 
607  | 93  |       else  | 
608  | 93  |       { | 
609  | 93  |         tok->err = json_tokener_error_parse_comment;  | 
610  | 93  |         goto out;  | 
611  | 93  |       }  | 
612  | 2.96k  |       printbuf_memappend_checked(tok->pb, &c, 1);  | 
613  | 2.96k  |       break;  | 
614  |  |  | 
615  | 4.08k  |     case json_tokener_state_comment:  | 
616  | 4.08k  |     { | 
617  |  |       /* Advance until we change state */  | 
618  | 4.08k  |       const char *case_start = str;  | 
619  | 512k  |       while (c != '*')  | 
620  | 508k  |       { | 
621  | 508k  |         if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))  | 
622  | 180  |         { | 
623  | 180  |           printbuf_memappend_checked(tok->pb, case_start,  | 
624  | 180  |                                      str - case_start);  | 
625  | 180  |           goto out;  | 
626  | 180  |         }  | 
627  | 508k  |       }  | 
628  | 3.90k  |       printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start);  | 
629  | 3.90k  |       state = json_tokener_state_comment_end;  | 
630  | 3.90k  |     }  | 
631  | 0  |     break;  | 
632  |  |  | 
633  | 2.21k  |     case json_tokener_state_comment_eol:  | 
634  | 2.21k  |     { | 
635  |  |       /* Advance until we change state */  | 
636  | 2.21k  |       const char *case_start = str;  | 
637  | 229k  |       while (c != '\n')  | 
638  | 227k  |       { | 
639  | 227k  |         if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))  | 
640  | 139  |         { | 
641  | 139  |           printbuf_memappend_checked(tok->pb, case_start,  | 
642  | 139  |                                      str - case_start);  | 
643  | 139  |           goto out;  | 
644  | 139  |         }  | 
645  | 227k  |       }  | 
646  | 2.07k  |       printbuf_memappend_checked(tok->pb, case_start, str - case_start);  | 
647  | 2.07k  |       MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); | 
648  | 2.07k  |       state = json_tokener_state_eatws;  | 
649  | 2.07k  |     }  | 
650  | 0  |     break;  | 
651  |  |  | 
652  | 3.90k  |     case json_tokener_state_comment_end:  | 
653  | 3.90k  |       printbuf_memappend_checked(tok->pb, &c, 1);  | 
654  | 3.90k  |       if (c == '/')  | 
655  | 553  |       { | 
656  | 553  |         MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); | 
657  | 553  |         state = json_tokener_state_eatws;  | 
658  | 553  |       }  | 
659  | 3.34k  |       else  | 
660  | 3.34k  |       { | 
661  | 3.34k  |         state = json_tokener_state_comment;  | 
662  | 3.34k  |       }  | 
663  | 3.90k  |       break;  | 
664  |  |  | 
665  | 154k  |     case json_tokener_state_string:  | 
666  | 154k  |     { | 
667  |  |       /* Advance until we change state */  | 
668  | 154k  |       const char *case_start = str;  | 
669  | 2.68M  |       while (1)  | 
670  | 2.68M  |       { | 
671  | 2.68M  |         if (c == tok->quote_char)  | 
672  | 90.9k  |         { | 
673  | 90.9k  |           printbuf_memappend_checked(tok->pb, case_start,  | 
674  | 90.9k  |                                      str - case_start);  | 
675  | 90.9k  |           current =  | 
676  | 90.9k  |               json_object_new_string_len(tok->pb->buf, tok->pb->bpos);  | 
677  | 90.9k  |           if (current == NULL)  | 
678  | 0  |           { | 
679  | 0  |             tok->err = json_tokener_error_memory;  | 
680  | 0  |             goto out;  | 
681  | 0  |           }  | 
682  | 90.9k  |           saved_state = json_tokener_state_finish;  | 
683  | 90.9k  |           state = json_tokener_state_eatws;  | 
684  | 90.9k  |           break;  | 
685  | 90.9k  |         }  | 
686  | 2.59M  |         else if (c == '\\')  | 
687  | 63.1k  |         { | 
688  | 63.1k  |           printbuf_memappend_checked(tok->pb, case_start,  | 
689  | 63.1k  |                                      str - case_start);  | 
690  | 63.1k  |           saved_state = json_tokener_state_string;  | 
691  | 63.1k  |           state = json_tokener_state_string_escape;  | 
692  | 63.1k  |           break;  | 
693  | 63.1k  |         }  | 
694  | 2.52M  |         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  | 2.52M  |         if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))  | 
701  | 264  |         { | 
702  | 264  |           printbuf_memappend_checked(tok->pb, case_start,  | 
703  | 264  |                                      str - case_start);  | 
704  | 264  |           goto out;  | 
705  | 264  |         }  | 
706  | 2.52M  |       }  | 
707  | 154k  |     }  | 
708  | 154k  |     break;  | 
709  |  |  | 
710  | 154k  |     case json_tokener_state_string_escape:  | 
711  | 74.6k  |       switch (c)  | 
712  | 74.6k  |       { | 
713  | 13.0k  |       case '"':  | 
714  | 43.6k  |       case '\\':  | 
715  | 44.0k  |       case '/':  | 
716  | 44.0k  |         printbuf_memappend_checked(tok->pb, &c, 1);  | 
717  | 44.0k  |         state = saved_state;  | 
718  | 44.0k  |         break;  | 
719  | 771  |       case 'b':  | 
720  | 22.9k  |       case 'n':  | 
721  | 23.6k  |       case 'r':  | 
722  | 24.7k  |       case 't':  | 
723  | 25.2k  |       case 'f':  | 
724  | 25.2k  |         if (c == 'b')  | 
725  | 771  |           printbuf_memappend_checked(tok->pb, "\b", 1);  | 
726  | 24.5k  |         else if (c == 'n')  | 
727  | 22.2k  |           printbuf_memappend_checked(tok->pb, "\n", 1);  | 
728  | 2.32k  |         else if (c == 'r')  | 
729  | 632  |           printbuf_memappend_checked(tok->pb, "\r", 1);  | 
730  | 1.69k  |         else if (c == 't')  | 
731  | 1.17k  |           printbuf_memappend_checked(tok->pb, "\t", 1);  | 
732  | 518  |         else if (c == 'f')  | 
733  | 518  |           printbuf_memappend_checked(tok->pb, "\f", 1);  | 
734  | 25.2k  |         state = saved_state;  | 
735  | 25.2k  |         break;  | 
736  | 5.26k  |       case 'u':  | 
737  | 5.26k  |         tok->ucs_char = 0;  | 
738  | 5.26k  |         tok->st_pos = 0;  | 
739  | 5.26k  |         state = json_tokener_state_escape_unicode;  | 
740  | 5.26k  |         break;  | 
741  | 34  |       default: tok->err = json_tokener_error_parse_string; goto out;  | 
742  | 74.6k  |       }  | 
743  | 74.5k  |       break;  | 
744  |  |  | 
745  |  |       // ===================================================  | 
746  |  |  | 
747  | 74.5k  |     case json_tokener_state_escape_unicode:  | 
748  | 6.99k  |     { | 
749  |  |       /* Handle a 4-byte \uNNNN sequence, or two sequences if a surrogate pair */  | 
750  | 27.7k  |       while (1)  | 
751  | 27.7k  |       { | 
752  | 27.7k  |         if (!c || !is_hex_char(c))  | 
753  | 87  |         { | 
754  | 87  |           tok->err = json_tokener_error_parse_string;  | 
755  | 87  |           goto out;  | 
756  | 87  |         }  | 
757  | 27.7k  |         tok->ucs_char |=  | 
758  | 27.7k  |             ((unsigned int)jt_hexdigit(c) << ((3 - tok->st_pos) * 4));  | 
759  | 27.7k  |         tok->st_pos++;  | 
760  | 27.7k  |         if (tok->st_pos >= 4)  | 
761  | 6.90k  |           break;  | 
762  |  |  | 
763  | 20.7k  |         (void)ADVANCE_CHAR(str, tok);  | 
764  | 20.7k  |         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  | 20.7k  |       }  | 
775  | 6.90k  |       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  | 6.90k  |       if (tok->high_surrogate)  | 
781  | 1.71k  |       { | 
782  | 1.71k  |         if (IS_LOW_SURROGATE(tok->ucs_char))  | 
783  | 843  |         { | 
784  |  |           /* Recalculate the ucs_char, then fall thru to process normally */  | 
785  | 843  |           tok->ucs_char = DECODE_SURROGATE_PAIR(tok->high_surrogate,  | 
786  | 843  |                                                 tok->ucs_char);  | 
787  | 843  |         }  | 
788  | 874  |         else  | 
789  | 874  |         { | 
790  |  |           /* High surrogate was not followed by a low surrogate  | 
791  |  |            * Replace the high and process the rest normally  | 
792  |  |            */  | 
793  | 874  |           printbuf_memappend_checked(tok->pb,  | 
794  | 874  |                                      (char *)utf8_replacement_char, 3);  | 
795  | 874  |         }  | 
796  | 1.71k  |         tok->high_surrogate = 0;  | 
797  | 1.71k  |       }  | 
798  |  |  | 
799  | 6.90k  |       if (tok->ucs_char < 0x80)  | 
800  | 1.44k  |       { | 
801  | 1.44k  |         unsigned char unescaped_utf[1];  | 
802  | 1.44k  |         unescaped_utf[0] = tok->ucs_char;  | 
803  | 1.44k  |         printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1);  | 
804  | 1.44k  |       }  | 
805  | 5.46k  |       else if (tok->ucs_char < 0x800)  | 
806  | 423  |       { | 
807  | 423  |         unsigned char unescaped_utf[2];  | 
808  | 423  |         unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);  | 
809  | 423  |         unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);  | 
810  | 423  |         printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2);  | 
811  | 423  |       }  | 
812  | 5.04k  |       else if (IS_HIGH_SURROGATE(tok->ucs_char))  | 
813  | 2.97k  |       { | 
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  | 2.97k  |         tok->high_surrogate = tok->ucs_char;  | 
829  | 2.97k  |         tok->ucs_char = 0;  | 
830  | 2.97k  |         state = json_tokener_state_escape_unicode_need_escape;  | 
831  | 2.97k  |         break;  | 
832  | 2.97k  |       }  | 
833  | 2.06k  |       else if (IS_LOW_SURROGATE(tok->ucs_char))  | 
834  | 596  |       { | 
835  |  |         /* Got a low surrogate not preceded by a high */  | 
836  | 596  |         printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);  | 
837  | 596  |       }  | 
838  | 1.46k  |       else if (tok->ucs_char < 0x10000)  | 
839  | 726  |       { | 
840  | 726  |         unsigned char unescaped_utf[3];  | 
841  | 726  |         unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);  | 
842  | 726  |         unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);  | 
843  | 726  |         unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);  | 
844  | 726  |         printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3);  | 
845  | 726  |       }  | 
846  | 742  |       else if (tok->ucs_char < 0x110000)  | 
847  | 742  |       { | 
848  | 742  |         unsigned char unescaped_utf[4];  | 
849  | 742  |         unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);  | 
850  | 742  |         unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);  | 
851  | 742  |         unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);  | 
852  | 742  |         unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);  | 
853  | 742  |         printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4);  | 
854  | 742  |       }  | 
855  | 0  |       else  | 
856  | 0  |       { | 
857  |  |         /* Don't know what we got--insert the replacement char */  | 
858  | 0  |         printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);  | 
859  | 0  |       }  | 
860  | 3.92k  |       state = saved_state; // i.e. _state_string or _state_object_field  | 
861  | 3.92k  |     }  | 
862  | 0  |     break;  | 
863  |  |  | 
864  | 2.97k  |     case json_tokener_state_escape_unicode_need_escape:  | 
865  |  |       // We get here after processing a high_surrogate  | 
866  |  |       // require a '\\' char  | 
867  | 2.97k  |       if (!c || c != '\\')  | 
868  | 658  |       { | 
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  | 658  |         printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);  | 
874  | 658  |         tok->high_surrogate = 0;  | 
875  | 658  |         tok->ucs_char = 0;  | 
876  | 658  |         tok->st_pos = 0;  | 
877  | 658  |         state = saved_state;  | 
878  | 658  |         goto redo_char;  | 
879  | 658  |       }  | 
880  | 2.31k  |       state = json_tokener_state_escape_unicode_need_u;  | 
881  | 2.31k  |       break;  | 
882  |  |  | 
883  | 2.31k  |     case json_tokener_state_escape_unicode_need_u:  | 
884  |  |       /* We already had a \ char, check that it's \u */  | 
885  | 2.31k  |       if (!c || c != 'u')  | 
886  | 593  |       { | 
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  | 593  |         printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3);  | 
893  | 593  |         tok->high_surrogate = 0;  | 
894  | 593  |         tok->ucs_char = 0;  | 
895  | 593  |         tok->st_pos = 0;  | 
896  | 593  |         state = json_tokener_state_string_escape;  | 
897  | 593  |         goto redo_char;  | 
898  | 593  |       }  | 
899  | 1.72k  |       state = json_tokener_state_escape_unicode;  | 
900  | 1.72k  |       break;  | 
901  |  |  | 
902  |  |       // ===================================================  | 
903  |  |  | 
904  | 9.07k  |     case json_tokener_state_boolean:  | 
905  | 9.07k  |     { | 
906  | 9.07k  |       int size1, size2;  | 
907  | 9.07k  |       printbuf_memappend_checked(tok->pb, &c, 1);  | 
908  | 9.07k  |       size1 = json_min(tok->st_pos + 1, json_true_str_len);  | 
909  | 9.07k  |       size2 = json_min(tok->st_pos + 1, json_false_str_len);  | 
910  | 9.07k  |       if ((!(tok->flags & JSON_TOKENER_STRICT) &&  | 
911  | 9.07k  |            strncasecmp(json_true_str, tok->pb->buf, size1) == 0) ||  | 
912  | 9.07k  |           (strncmp(json_true_str, tok->pb->buf, size1) == 0))  | 
913  | 5.44k  |       { | 
914  | 5.44k  |         if (tok->st_pos == json_true_str_len)  | 
915  | 1.06k  |         { | 
916  | 1.06k  |           current = json_object_new_boolean(1);  | 
917  | 1.06k  |           if (current == NULL)  | 
918  | 0  |           { | 
919  | 0  |             tok->err = json_tokener_error_memory;  | 
920  | 0  |             goto out;  | 
921  | 0  |           }  | 
922  | 1.06k  |           saved_state = json_tokener_state_finish;  | 
923  | 1.06k  |           state = json_tokener_state_eatws;  | 
924  | 1.06k  |           goto redo_char;  | 
925  | 1.06k  |         }  | 
926  | 5.44k  |       }  | 
927  | 3.63k  |       else if ((!(tok->flags & JSON_TOKENER_STRICT) &&  | 
928  | 3.63k  |                 strncasecmp(json_false_str, tok->pb->buf, size2) == 0) ||  | 
929  | 3.63k  |                (strncmp(json_false_str, tok->pb->buf, size2) == 0))  | 
930  | 3.48k  |       { | 
931  | 3.48k  |         if (tok->st_pos == json_false_str_len)  | 
932  | 556  |         { | 
933  | 556  |           current = json_object_new_boolean(0);  | 
934  | 556  |           if (current == NULL)  | 
935  | 0  |           { | 
936  | 0  |             tok->err = json_tokener_error_memory;  | 
937  | 0  |             goto out;  | 
938  | 0  |           }  | 
939  | 556  |           saved_state = json_tokener_state_finish;  | 
940  | 556  |           state = json_tokener_state_eatws;  | 
941  | 556  |           goto redo_char;  | 
942  | 556  |         }  | 
943  | 3.48k  |       }  | 
944  | 152  |       else  | 
945  | 152  |       { | 
946  | 152  |         tok->err = json_tokener_error_parse_boolean;  | 
947  | 152  |         goto out;  | 
948  | 152  |       }  | 
949  | 7.30k  |       tok->st_pos++;  | 
950  | 7.30k  |     }  | 
951  | 0  |     break;  | 
952  |  |  | 
953  | 189k  |     case json_tokener_state_number:  | 
954  | 189k  |     { | 
955  |  |       /* Advance until we change state */  | 
956  | 189k  |       const char *case_start = str;  | 
957  | 189k  |       int case_len = 0;  | 
958  | 189k  |       int is_exponent = 0;  | 
959  | 189k  |       int neg_sign_ok = 1;  | 
960  | 189k  |       int pos_sign_ok = 0;  | 
961  | 189k  |       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  | 533k  |       while (c && ((c >= '0' && c <= '9') ||  | 
986  | 533k  |                    (!is_exponent && (c == 'e' || c == 'E')) ||  | 
987  | 533k  |                    (neg_sign_ok && c == '-') || (pos_sign_ok && c == '+') ||  | 
988  | 533k  |                    (!tok->is_double && c == '.')))  | 
989  | 343k  |       { | 
990  | 343k  |         pos_sign_ok = neg_sign_ok = 0;  | 
991  | 343k  |         ++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  | 343k  |         switch (c)  | 
1000  | 343k  |         { | 
1001  | 1.01k  |         case '.':  | 
1002  | 1.01k  |           tok->is_double = 1;  | 
1003  | 1.01k  |           pos_sign_ok = 1;  | 
1004  | 1.01k  |           neg_sign_ok = 1;  | 
1005  | 1.01k  |           break;  | 
1006  | 2.14k  |         case 'e': /* FALLTHRU */  | 
1007  | 3.47k  |         case 'E':  | 
1008  | 3.47k  |           is_exponent = 1;  | 
1009  | 3.47k  |           tok->is_double = 1;  | 
1010  |  |           /* the exponent part can begin with a negative sign */  | 
1011  | 3.47k  |           pos_sign_ok = neg_sign_ok = 1;  | 
1012  | 3.47k  |           break;  | 
1013  | 339k  |         default: break;  | 
1014  | 343k  |         }  | 
1015  |  |  | 
1016  | 343k  |         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  | 343k  |       }  | 
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  | 189k  |       if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' &&  | 
1031  | 189k  |           c != 'I' && c != 'i' && !is_ws_char(c))  | 
1032  | 278  |       { | 
1033  | 278  |         tok->err = json_tokener_error_parse_number;  | 
1034  | 278  |         goto out;  | 
1035  | 278  |       }  | 
1036  | 189k  |       if (case_len > 0)  | 
1037  | 189k  |         printbuf_memappend_checked(tok->pb, case_start, case_len);  | 
1038  |  |  | 
1039  |  |       // Check for -Infinity  | 
1040  | 189k  |       if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I'))  | 
1041  | 483  |       { | 
1042  | 483  |         state = json_tokener_state_inf;  | 
1043  | 483  |         tok->st_pos = 0;  | 
1044  | 483  |         goto redo_char;  | 
1045  | 483  |       }  | 
1046  | 189k  |       if (tok->is_double && !(tok->flags & JSON_TOKENER_STRICT))  | 
1047  | 3.94k  |       { | 
1048  |  |         /* Trim some chars off the end, to allow things  | 
1049  |  |            like "123e+" to parse ok. */  | 
1050  | 9.20k  |         while (printbuf_length(tok->pb) > 1)  | 
1051  | 7.03k  |         { | 
1052  | 7.03k  |           char last_char = tok->pb->buf[printbuf_length(tok->pb) - 1];  | 
1053  | 7.03k  |           if (last_char != 'e' && last_char != 'E' &&  | 
1054  | 7.03k  |               last_char != '-' && last_char != '+')  | 
1055  | 1.78k  |           { | 
1056  | 1.78k  |             break;  | 
1057  | 1.78k  |           }  | 
1058  | 5.25k  |           tok->pb->buf[printbuf_length(tok->pb) - 1] = '\0';  | 
1059  | 5.25k  |           printbuf_length(tok->pb)--;  | 
1060  | 5.25k  |         }  | 
1061  | 3.94k  |       }  | 
1062  | 189k  |     }  | 
1063  | 0  |       { | 
1064  | 189k  |         int64_t num64;  | 
1065  | 189k  |         uint64_t numuint64;  | 
1066  | 189k  |         double numd;  | 
1067  | 189k  |         if (!tok->is_double && tok->pb->buf[0] == '-' &&  | 
1068  | 189k  |             json_parse_int64(tok->pb->buf, &num64) == 0)  | 
1069  | 2.64k  |         { | 
1070  | 2.64k  |           if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT))  | 
1071  | 0  |           { | 
1072  | 0  |             tok->err = json_tokener_error_parse_number;  | 
1073  | 0  |             goto out;  | 
1074  | 0  |           }  | 
1075  | 2.64k  |           current = json_object_new_int64(num64);  | 
1076  | 2.64k  |           if (current == NULL)  | 
1077  | 0  |           { | 
1078  | 0  |             tok->err = json_tokener_error_memory;  | 
1079  | 0  |             goto out;  | 
1080  | 0  |           }  | 
1081  | 2.64k  |         }  | 
1082  | 186k  |         else if (!tok->is_double && tok->pb->buf[0] != '-' &&  | 
1083  | 186k  |                  json_parse_uint64(tok->pb->buf, &numuint64) == 0)  | 
1084  | 182k  |         { | 
1085  | 182k  |           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  | 182k  |           if (numuint64 && tok->pb->buf[0] == '0' &&  | 
1091  | 182k  |               (tok->flags & JSON_TOKENER_STRICT))  | 
1092  | 0  |           { | 
1093  | 0  |             tok->err = json_tokener_error_parse_number;  | 
1094  | 0  |             goto out;  | 
1095  | 0  |           }  | 
1096  | 182k  |           if (numuint64 <= INT64_MAX)  | 
1097  | 181k  |           { | 
1098  | 181k  |             num64 = (uint64_t)numuint64;  | 
1099  | 181k  |             current = json_object_new_int64(num64);  | 
1100  | 181k  |             if (current == NULL)  | 
1101  | 0  |             { | 
1102  | 0  |               tok->err = json_tokener_error_memory;  | 
1103  | 0  |               goto out;  | 
1104  | 0  |             }  | 
1105  | 181k  |           }  | 
1106  | 862  |           else  | 
1107  | 862  |           { | 
1108  | 862  |             current = json_object_new_uint64(numuint64);  | 
1109  | 862  |             if (current == NULL)  | 
1110  | 0  |             { | 
1111  | 0  |               tok->err = json_tokener_error_memory;  | 
1112  | 0  |               goto out;  | 
1113  | 0  |             }  | 
1114  | 862  |           }  | 
1115  | 182k  |         }  | 
1116  | 3.98k  |         else if (tok->is_double &&  | 
1117  | 3.98k  |                  json_tokener_parse_double(  | 
1118  | 3.94k  |                      tok->pb->buf, printbuf_length(tok->pb), &numd) == 0)  | 
1119  | 3.92k  |         { | 
1120  | 3.92k  |           current = json_object_new_double_s(numd, tok->pb->buf);  | 
1121  | 3.92k  |           if (current == NULL)  | 
1122  | 0  |           { | 
1123  | 0  |             tok->err = json_tokener_error_memory;  | 
1124  | 0  |             goto out;  | 
1125  | 0  |           }  | 
1126  | 3.92k  |         }  | 
1127  | 59  |         else  | 
1128  | 59  |         { | 
1129  | 59  |           tok->err = json_tokener_error_parse_number;  | 
1130  | 59  |           goto out;  | 
1131  | 59  |         }  | 
1132  | 189k  |         saved_state = json_tokener_state_finish;  | 
1133  | 189k  |         state = json_tokener_state_eatws;  | 
1134  | 189k  |         goto redo_char;  | 
1135  | 189k  |       }  | 
1136  | 0  |       break;  | 
1137  |  |  | 
1138  | 207k  |     case json_tokener_state_array_after_sep:  | 
1139  | 224k  |     case json_tokener_state_array:  | 
1140  | 224k  |       if (c == ']')  | 
1141  | 1.92k  |       { | 
1142  |  |         // Minimize memory usage; assume parsed objs are unlikely to be changed  | 
1143  | 1.92k  |         json_object_array_shrink(current, 0);  | 
1144  |  |  | 
1145  | 1.92k  |         if (state == json_tokener_state_array_after_sep &&  | 
1146  | 1.92k  |             (tok->flags & JSON_TOKENER_STRICT))  | 
1147  | 0  |         { | 
1148  | 0  |           tok->err = json_tokener_error_parse_unexpected;  | 
1149  | 0  |           goto out;  | 
1150  | 0  |         }  | 
1151  | 1.92k  |         saved_state = json_tokener_state_finish;  | 
1152  | 1.92k  |         state = json_tokener_state_eatws;  | 
1153  | 1.92k  |       }  | 
1154  | 222k  |       else  | 
1155  | 222k  |       { | 
1156  | 222k  |         if (tok->depth >= tok->max_depth - 1)  | 
1157  | 4  |         { | 
1158  | 4  |           tok->err = json_tokener_error_depth;  | 
1159  | 4  |           goto out;  | 
1160  | 4  |         }  | 
1161  | 222k  |         state = json_tokener_state_array_add;  | 
1162  | 222k  |         tok->depth++;  | 
1163  | 222k  |         json_tokener_reset_level(tok, tok->depth);  | 
1164  | 222k  |         goto redo_char;  | 
1165  | 222k  |       }  | 
1166  | 1.92k  |       break;  | 
1167  |  |  | 
1168  | 220k  |     case json_tokener_state_array_add:  | 
1169  | 220k  |       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  | 220k  |       saved_state = json_tokener_state_array_sep;  | 
1175  | 220k  |       state = json_tokener_state_eatws;  | 
1176  | 220k  |       goto redo_char;  | 
1177  |  |  | 
1178  | 220k  |     case json_tokener_state_array_sep:  | 
1179  | 220k  |       if (c == ']')  | 
1180  | 12.5k  |       { | 
1181  |  |         // Minimize memory usage; assume parsed objs are unlikely to be changed  | 
1182  | 12.5k  |         json_object_array_shrink(current, 0);  | 
1183  |  |  | 
1184  | 12.5k  |         saved_state = json_tokener_state_finish;  | 
1185  | 12.5k  |         state = json_tokener_state_eatws;  | 
1186  | 12.5k  |       }  | 
1187  | 207k  |       else if (c == ',')  | 
1188  | 207k  |       { | 
1189  | 207k  |         saved_state = json_tokener_state_array_after_sep;  | 
1190  | 207k  |         state = json_tokener_state_eatws;  | 
1191  | 207k  |       }  | 
1192  | 190  |       else  | 
1193  | 190  |       { | 
1194  | 190  |         tok->err = json_tokener_error_parse_array;  | 
1195  | 190  |         goto out;  | 
1196  | 190  |       }  | 
1197  | 220k  |       break;  | 
1198  |  |  | 
1199  | 220k  |     case json_tokener_state_object_field_start:  | 
1200  | 166k  |     case json_tokener_state_object_field_start_after_sep:  | 
1201  | 166k  |       if (c == '}')  | 
1202  | 22.6k  |       { | 
1203  | 22.6k  |         if (state == json_tokener_state_object_field_start_after_sep &&  | 
1204  | 22.6k  |             (tok->flags & JSON_TOKENER_STRICT))  | 
1205  | 0  |         { | 
1206  | 0  |           tok->err = json_tokener_error_parse_unexpected;  | 
1207  | 0  |           goto out;  | 
1208  | 0  |         }  | 
1209  | 22.6k  |         saved_state = json_tokener_state_finish;  | 
1210  | 22.6k  |         state = json_tokener_state_eatws;  | 
1211  | 22.6k  |       }  | 
1212  | 143k  |       else if (c == '"' || c == '\'')  | 
1213  | 143k  |       { | 
1214  | 143k  |         tok->quote_char = c;  | 
1215  | 143k  |         printbuf_reset(tok->pb);  | 
1216  | 143k  |         state = json_tokener_state_object_field;  | 
1217  | 143k  |       }  | 
1218  | 56  |       else  | 
1219  | 56  |       { | 
1220  | 56  |         tok->err = json_tokener_error_parse_object_key_name;  | 
1221  | 56  |         goto out;  | 
1222  | 56  |       }  | 
1223  | 166k  |       break;  | 
1224  |  |  | 
1225  | 166k  |     case json_tokener_state_object_field:  | 
1226  | 154k  |     { | 
1227  |  |       /* Advance until we change state */  | 
1228  | 154k  |       const char *case_start = str;  | 
1229  | 2.21M  |       while (1)  | 
1230  | 2.21M  |       { | 
1231  | 2.21M  |         if (c == tok->quote_char)  | 
1232  | 143k  |         { | 
1233  | 143k  |           printbuf_memappend_checked(tok->pb, case_start,  | 
1234  | 143k  |                                      str - case_start);  | 
1235  | 143k  |           obj_field_name = strdup(tok->pb->buf);  | 
1236  | 143k  |           if (obj_field_name == NULL)  | 
1237  | 0  |           { | 
1238  | 0  |             tok->err = json_tokener_error_memory;  | 
1239  | 0  |             goto out;  | 
1240  | 0  |           }  | 
1241  | 143k  |           saved_state = json_tokener_state_object_field_end;  | 
1242  | 143k  |           state = json_tokener_state_eatws;  | 
1243  | 143k  |           break;  | 
1244  | 143k  |         }  | 
1245  | 2.07M  |         else if (c == '\\')  | 
1246  | 10.8k  |         { | 
1247  | 10.8k  |           printbuf_memappend_checked(tok->pb, case_start,  | 
1248  | 10.8k  |                                      str - case_start);  | 
1249  | 10.8k  |           saved_state = json_tokener_state_object_field;  | 
1250  | 10.8k  |           state = json_tokener_state_string_escape;  | 
1251  | 10.8k  |           break;  | 
1252  | 10.8k  |         }  | 
1253  | 2.06M  |         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  | 2.06M  |         if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok))  | 
1260  | 201  |         { | 
1261  | 201  |           printbuf_memappend_checked(tok->pb, case_start,  | 
1262  | 201  |                                      str - case_start);  | 
1263  | 201  |           goto out;  | 
1264  | 201  |         }  | 
1265  | 2.06M  |       }  | 
1266  | 154k  |     }  | 
1267  | 154k  |     break;  | 
1268  |  |  | 
1269  | 154k  |     case json_tokener_state_object_field_end:  | 
1270  | 142k  |       if (c == ':')  | 
1271  | 142k  |       { | 
1272  | 142k  |         saved_state = json_tokener_state_object_value;  | 
1273  | 142k  |         state = json_tokener_state_eatws;  | 
1274  | 142k  |       }  | 
1275  | 143  |       else  | 
1276  | 143  |       { | 
1277  | 143  |         tok->err = json_tokener_error_parse_object_key_sep;  | 
1278  | 143  |         goto out;  | 
1279  | 143  |       }  | 
1280  | 142k  |       break;  | 
1281  |  |  | 
1282  | 142k  |     case json_tokener_state_object_value:  | 
1283  | 142k  |       if (tok->depth >= tok->max_depth - 1)  | 
1284  | 3  |       { | 
1285  | 3  |         tok->err = json_tokener_error_depth;  | 
1286  | 3  |         goto out;  | 
1287  | 3  |       }  | 
1288  | 142k  |       state = json_tokener_state_object_value_add;  | 
1289  | 142k  |       tok->depth++;  | 
1290  | 142k  |       json_tokener_reset_level(tok, tok->depth);  | 
1291  | 142k  |       goto redo_char;  | 
1292  |  |  | 
1293  | 140k  |     case json_tokener_state_object_value_add:  | 
1294  | 140k  |       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  | 140k  |       free(obj_field_name);  | 
1300  | 140k  |       obj_field_name = NULL;  | 
1301  | 140k  |       saved_state = json_tokener_state_object_sep;  | 
1302  | 140k  |       state = json_tokener_state_eatws;  | 
1303  | 140k  |       goto redo_char;  | 
1304  |  |  | 
1305  | 140k  |     case json_tokener_state_object_sep:  | 
1306  |  |       /* { */ | 
1307  | 140k  |       if (c == '}')  | 
1308  | 36.7k  |       { | 
1309  | 36.7k  |         saved_state = json_tokener_state_finish;  | 
1310  | 36.7k  |         state = json_tokener_state_eatws;  | 
1311  | 36.7k  |       }  | 
1312  | 104k  |       else if (c == ',')  | 
1313  | 103k  |       { | 
1314  | 103k  |         saved_state = json_tokener_state_object_field_start_after_sep;  | 
1315  | 103k  |         state = json_tokener_state_eatws;  | 
1316  | 103k  |       }  | 
1317  | 287  |       else  | 
1318  | 287  |       { | 
1319  | 287  |         tok->err = json_tokener_error_parse_object_value_sep;  | 
1320  | 287  |         goto out;  | 
1321  | 287  |       }  | 
1322  | 140k  |       break;  | 
1323  | 4.60M  |     }  | 
1324  | 1.31M  |     (void)ADVANCE_CHAR(str, tok);  | 
1325  | 1.31M  |     if (!c) // This is the char *before* advancing  | 
1326  | 11  |       break;  | 
1327  | 1.31M  |   } /* while(PEEK_CHAR) */  | 
1328  |  |  | 
1329  | 11.0k  | out:  | 
1330  | 11.0k  |   if ((tok->flags & JSON_TOKENER_VALIDATE_UTF8) && (nBytes != 0))  | 
1331  | 0  |   { | 
1332  | 0  |     tok->err = json_tokener_error_parse_utf8_string;  | 
1333  | 0  |   }  | 
1334  | 11.0k  |   if (c && (state == json_tokener_state_finish) && (tok->depth == 0) &&  | 
1335  | 11.0k  |       (tok->flags & (JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS)) ==  | 
1336  | 113  |           JSON_TOKENER_STRICT)  | 
1337  | 0  |   { | 
1338  |  |     /* unexpected char after JSON data */  | 
1339  | 0  |     tok->err = json_tokener_error_parse_unexpected;  | 
1340  | 0  |   }  | 
1341  | 11.0k  |   if (!c)  | 
1342  | 9.28k  |   { | 
1343  |  |     /* We hit an eof char (0) */  | 
1344  | 9.28k  |     if (state != json_tokener_state_finish && saved_state != json_tokener_state_finish)  | 
1345  | 844  |       tok->err = json_tokener_error_parse_eof;  | 
1346  | 9.28k  |   }  | 
1347  |  |  | 
1348  | 11.0k  | #ifdef HAVE_USELOCALE  | 
1349  | 11.0k  |   uselocale(oldlocale);  | 
1350  | 11.0k  |   freelocale(newloc);  | 
1351  |  | #elif defined(HAVE_SETLOCALE)  | 
1352  |  |   setlocale(LC_NUMERIC, oldlocale);  | 
1353  |  |   free(oldlocale);  | 
1354  |  | #endif  | 
1355  |  |  | 
1356  | 11.0k  |   if (tok->err == json_tokener_success)  | 
1357  | 8.55k  |   { | 
1358  | 8.55k  |     json_object *ret = json_object_get(current);  | 
1359  | 8.55k  |     int ii;  | 
1360  |  |  | 
1361  |  |     /* Partially reset, so we parse additional objects on subsequent calls. */  | 
1362  | 17.4k  |     for (ii = tok->depth; ii >= 0; ii--)  | 
1363  | 8.89k  |       json_tokener_reset_level(tok, ii);  | 
1364  | 8.55k  |     return ret;  | 
1365  | 8.55k  |   }  | 
1366  |  |  | 
1367  | 2.45k  |   MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", json_tokener_errors[tok->err], | 
1368  | 2.45k  |            tok->char_offset);  | 
1369  | 2.45k  |   return NULL;  | 
1370  | 11.0k  | }  | 
1371  |  |  | 
1372  |  | static json_bool json_tokener_validate_utf8(const char c, unsigned int *nBytes)  | 
1373  | 0  | { | 
1374  | 0  |   unsigned char chr = c;  | 
1375  | 0  |   if (*nBytes == 0)  | 
1376  | 0  |   { | 
1377  | 0  |     if (chr >= 0x80)  | 
1378  | 0  |     { | 
1379  | 0  |       if ((chr & 0xe0) == 0xc0)  | 
1380  | 0  |         *nBytes = 1;  | 
1381  | 0  |       else if ((chr & 0xf0) == 0xe0)  | 
1382  | 0  |         *nBytes = 2;  | 
1383  | 0  |       else if ((chr & 0xf8) == 0xf0)  | 
1384  | 0  |         *nBytes = 3;  | 
1385  | 0  |       else  | 
1386  | 0  |         return 0;  | 
1387  | 0  |     }  | 
1388  | 0  |   }  | 
1389  | 0  |   else  | 
1390  | 0  |   { | 
1391  | 0  |     if ((chr & 0xC0) != 0x80)  | 
1392  | 0  |       return 0;  | 
1393  | 0  |     (*nBytes)--;  | 
1394  | 0  |   }  | 
1395  | 0  |   return 1;  | 
1396  | 0  | }  | 
1397  |  |  | 
1398  |  | void json_tokener_set_flags(struct json_tokener *tok, int flags)  | 
1399  | 0  | { | 
1400  | 0  |   tok->flags = flags;  | 
1401  | 0  | }  | 
1402  |  |  | 
1403  |  | size_t json_tokener_get_parse_end(struct json_tokener *tok)  | 
1404  | 0  | { | 
1405  | 0  |   assert(tok->char_offset >= 0); /* Drop this line when char_offset becomes a size_t */  | 
1406  | 0  |   return (size_t)tok->char_offset;  | 
1407  | 0  | }  | 
1408  |  |  | 
1409  |  | static int json_tokener_parse_double(const char *buf, int len, double *retval)  | 
1410  | 3.94k  | { | 
1411  | 3.94k  |   char *end;  | 
1412  | 3.94k  |   *retval = strtod(buf, &end);  | 
1413  | 3.94k  |   if (buf + len == end)  | 
1414  | 3.92k  |     return 0; // It worked  | 
1415  | 27  |   return 1;  | 
1416  | 3.94k  | }  |