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