|
@@ -104,6 +104,7 @@ static const char *json_tokener_errors[] = { |
|
|
"success", |
|
|
"success", |
|
|
"continue", |
|
|
"continue", |
|
|
"nesting too deep", |
|
|
"nesting too deep", |
|
|
|
|
|
"out of memory", |
|
|
"unexpected end of data", |
|
|
"unexpected end of data", |
|
|
"unexpected character", |
|
|
"unexpected character", |
|
|
"null expected", |
|
|
"null expected", |
|
@@ -285,11 +286,24 @@ struct json_object *json_tokener_parse_verbose(const char *str, enum json_tokene |
|
|
|
|
|
|
|
|
/* ADVANCE_CHAR() macro: |
|
|
/* ADVANCE_CHAR() macro: |
|
|
* Increments str & tok->char_offset. |
|
|
* Increments str & tok->char_offset. |
|
|
* For convenience of existing conditionals, returns the old value of c (0 on eof) |
|
|
|
|
|
|
|
|
* For convenience of existing conditionals, returns the old value of c (0 on eof). |
|
|
* Implicit inputs: c var |
|
|
* Implicit inputs: c var |
|
|
*/ |
|
|
*/ |
|
|
#define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c) |
|
|
#define ADVANCE_CHAR(str, tok) (++(str), ((tok)->char_offset)++, c) |
|
|
|
|
|
|
|
|
|
|
|
/* printbuf_memappend_checked(p, s, l) macro: |
|
|
|
|
|
* Add string s of length l to printbuffer p. |
|
|
|
|
|
* If operation fails abort parse operation with memory error. |
|
|
|
|
|
*/ |
|
|
|
|
|
#define printbuf_memappend_checked(p, s, l) \ |
|
|
|
|
|
do { \ |
|
|
|
|
|
if (printbuf_memappend((p), (s), (l)) < 0) \ |
|
|
|
|
|
{ \ |
|
|
|
|
|
tok->err = json_tokener_error_memory; \ |
|
|
|
|
|
goto out; \ |
|
|
|
|
|
} \ |
|
|
|
|
|
} while (0) |
|
|
|
|
|
|
|
|
/* End optimization macro defs */ |
|
|
/* End optimization macro defs */ |
|
|
|
|
|
|
|
|
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len) |
|
|
struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len) |
|
@@ -337,7 +351,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
char *tmplocale; |
|
|
char *tmplocale; |
|
|
tmplocale = setlocale(LC_NUMERIC, NULL); |
|
|
tmplocale = setlocale(LC_NUMERIC, NULL); |
|
|
if (tmplocale) |
|
|
if (tmplocale) |
|
|
|
|
|
{ |
|
|
oldlocale = strdup(tmplocale); |
|
|
oldlocale = strdup(tmplocale); |
|
|
|
|
|
if (oldlocale == NULL) |
|
|
|
|
|
return NULL; |
|
|
|
|
|
} |
|
|
setlocale(LC_NUMERIC, "C"); |
|
|
setlocale(LC_NUMERIC, "C"); |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
@@ -359,7 +377,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) |
|
|
if (c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) |
|
|
{ |
|
|
{ |
|
|
printbuf_reset(tok->pb); |
|
|
printbuf_reset(tok->pb); |
|
|
printbuf_memappend_fast(tok->pb, &c, 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, &c, 1); |
|
|
state = json_tokener_state_comment_start; |
|
|
state = json_tokener_state_comment_start; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
@@ -377,14 +395,20 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
saved_state = json_tokener_state_object_field_start; |
|
|
saved_state = json_tokener_state_object_field_start; |
|
|
current = json_object_new_object(); |
|
|
current = json_object_new_object(); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
break; |
|
|
break; |
|
|
case '[': |
|
|
case '[': |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
saved_state = json_tokener_state_array; |
|
|
saved_state = json_tokener_state_array; |
|
|
current = json_object_new_array(); |
|
|
current = json_object_new_array(); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
break; |
|
|
break; |
|
|
case 'I': |
|
|
case 'I': |
|
|
case 'i': |
|
|
case 'i': |
|
@@ -487,7 +511,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
} |
|
|
} |
|
|
current = json_object_new_double(is_negative ? -INFINITY : INFINITY); |
|
|
current = json_object_new_double(is_negative ? -INFINITY : INFINITY); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
saved_state = json_tokener_state_finish; |
|
|
saved_state = json_tokener_state_finish; |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
goto redo_char; |
|
|
goto redo_char; |
|
@@ -497,7 +524,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
int size; |
|
|
int size; |
|
|
int size_nan; |
|
|
int size_nan; |
|
|
printbuf_memappend_fast(tok->pb, &c, 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, &c, 1); |
|
|
size = json_min(tok->st_pos + 1, json_null_str_len); |
|
|
size = json_min(tok->st_pos + 1, json_null_str_len); |
|
|
size_nan = json_min(tok->st_pos + 1, json_nan_str_len); |
|
|
size_nan = json_min(tok->st_pos + 1, json_nan_str_len); |
|
|
if ((!(tok->flags & JSON_TOKENER_STRICT) && |
|
|
if ((!(tok->flags & JSON_TOKENER_STRICT) && |
|
@@ -520,7 +547,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
current = json_object_new_double(NAN); |
|
|
current = json_object_new_double(NAN); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
saved_state = json_tokener_state_finish; |
|
|
saved_state = json_tokener_state_finish; |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
goto redo_char; |
|
|
goto redo_char; |
|
@@ -549,7 +579,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
tok->err = json_tokener_error_parse_comment; |
|
|
tok->err = json_tokener_error_parse_comment; |
|
|
goto out; |
|
|
goto out; |
|
|
} |
|
|
} |
|
|
printbuf_memappend_fast(tok->pb, &c, 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, &c, 1); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case json_tokener_state_comment: |
|
|
case json_tokener_state_comment: |
|
@@ -560,12 +590,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
goto out; |
|
|
goto out; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
printbuf_memappend_fast(tok->pb, case_start, 1 + str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, 1 + str - case_start); |
|
|
state = json_tokener_state_comment_end; |
|
|
state = json_tokener_state_comment_end; |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
@@ -578,19 +608,19 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
goto out; |
|
|
goto out; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
printbuf_memappend_fast(tok->pb, case_start, str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, str - case_start); |
|
|
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); |
|
|
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case json_tokener_state_comment_end: |
|
|
case json_tokener_state_comment_end: |
|
|
printbuf_memappend_fast(tok->pb, &c, 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, &c, 1); |
|
|
if (c == '/') |
|
|
if (c == '/') |
|
|
{ |
|
|
{ |
|
|
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); |
|
|
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); |
|
@@ -610,28 +640,31 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
if (c == tok->quote_char) |
|
|
if (c == tok->quote_char) |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
current = |
|
|
current = |
|
|
json_object_new_string_len(tok->pb->buf, tok->pb->bpos); |
|
|
json_object_new_string_len(tok->pb->buf, tok->pb->bpos); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
saved_state = json_tokener_state_finish; |
|
|
saved_state = json_tokener_state_finish; |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
else if (c == '\\') |
|
|
else if (c == '\\') |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
saved_state = json_tokener_state_string; |
|
|
saved_state = json_tokener_state_string; |
|
|
state = json_tokener_state_string_escape; |
|
|
state = json_tokener_state_string_escape; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
goto out; |
|
|
goto out; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@@ -644,7 +677,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
case '"': |
|
|
case '"': |
|
|
case '\\': |
|
|
case '\\': |
|
|
case '/': |
|
|
case '/': |
|
|
printbuf_memappend_fast(tok->pb, &c, 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, &c, 1); |
|
|
state = saved_state; |
|
|
state = saved_state; |
|
|
break; |
|
|
break; |
|
|
case 'b': |
|
|
case 'b': |
|
@@ -653,15 +686,15 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
case 't': |
|
|
case 't': |
|
|
case 'f': |
|
|
case 'f': |
|
|
if (c == 'b') |
|
|
if (c == 'b') |
|
|
printbuf_memappend_fast(tok->pb, "\b", 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, "\b", 1); |
|
|
else if (c == 'n') |
|
|
else if (c == 'n') |
|
|
printbuf_memappend_fast(tok->pb, "\n", 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, "\n", 1); |
|
|
else if (c == 'r') |
|
|
else if (c == 'r') |
|
|
printbuf_memappend_fast(tok->pb, "\r", 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, "\r", 1); |
|
|
else if (c == 't') |
|
|
else if (c == 't') |
|
|
printbuf_memappend_fast(tok->pb, "\t", 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, "\t", 1); |
|
|
else if (c == 'f') |
|
|
else if (c == 'f') |
|
|
printbuf_memappend_fast(tok->pb, "\f", 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, "\f", 1); |
|
|
state = saved_state; |
|
|
state = saved_state; |
|
|
break; |
|
|
break; |
|
|
case 'u': |
|
|
case 'u': |
|
@@ -721,8 +754,8 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
/* High surrogate was not followed by a low surrogate |
|
|
/* High surrogate was not followed by a low surrogate |
|
|
* Replace the high and process the rest normally |
|
|
* Replace the high and process the rest normally |
|
|
*/ |
|
|
*/ |
|
|
printbuf_memappend_fast(tok->pb, |
|
|
|
|
|
(char *)utf8_replacement_char, 3); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, |
|
|
|
|
|
(char *)utf8_replacement_char, 3); |
|
|
} |
|
|
} |
|
|
tok->high_surrogate = 0; |
|
|
tok->high_surrogate = 0; |
|
|
} |
|
|
} |
|
@@ -731,14 +764,14 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
unsigned char unescaped_utf[1]; |
|
|
unsigned char unescaped_utf[1]; |
|
|
unescaped_utf[0] = tok->ucs_char; |
|
|
unescaped_utf[0] = tok->ucs_char; |
|
|
printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 1); |
|
|
} |
|
|
} |
|
|
else if (tok->ucs_char < 0x800) |
|
|
else if (tok->ucs_char < 0x800) |
|
|
{ |
|
|
{ |
|
|
unsigned char unescaped_utf[2]; |
|
|
unsigned char unescaped_utf[2]; |
|
|
unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6); |
|
|
unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6); |
|
|
unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); |
|
|
unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); |
|
|
printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 2); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 2); |
|
|
} |
|
|
} |
|
|
else if (IS_HIGH_SURROGATE(tok->ucs_char)) |
|
|
else if (IS_HIGH_SURROGATE(tok->ucs_char)) |
|
|
{ |
|
|
{ |
|
@@ -764,7 +797,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
else if (IS_LOW_SURROGATE(tok->ucs_char)) |
|
|
else if (IS_LOW_SURROGATE(tok->ucs_char)) |
|
|
{ |
|
|
{ |
|
|
/* Got a low surrogate not preceded by a high */ |
|
|
/* Got a low surrogate not preceded by a high */ |
|
|
printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
} |
|
|
} |
|
|
else if (tok->ucs_char < 0x10000) |
|
|
else if (tok->ucs_char < 0x10000) |
|
|
{ |
|
|
{ |
|
@@ -772,7 +805,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12); |
|
|
unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12); |
|
|
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); |
|
|
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); |
|
|
unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f); |
|
|
unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f); |
|
|
printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 3); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 3); |
|
|
} |
|
|
} |
|
|
else if (tok->ucs_char < 0x110000) |
|
|
else if (tok->ucs_char < 0x110000) |
|
|
{ |
|
|
{ |
|
@@ -781,12 +814,12 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f); |
|
|
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f); |
|
|
unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); |
|
|
unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); |
|
|
unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f); |
|
|
unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f); |
|
|
printbuf_memappend_fast(tok->pb, (char *)unescaped_utf, 4); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)unescaped_utf, 4); |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
/* Don't know what we got--insert the replacement char */ |
|
|
/* Don't know what we got--insert the replacement char */ |
|
|
printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
} |
|
|
} |
|
|
state = saved_state; // i.e. _state_string or _state_object_field |
|
|
state = saved_state; // i.e. _state_string or _state_object_field |
|
|
} |
|
|
} |
|
@@ -801,7 +834,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
* it. Put a replacement char in for the high surrogate |
|
|
* it. Put a replacement char in for the high surrogate |
|
|
* and pop back up to _state_string or _state_object_field. |
|
|
* and pop back up to _state_string or _state_object_field. |
|
|
*/ |
|
|
*/ |
|
|
printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
tok->high_surrogate = 0; |
|
|
tok->high_surrogate = 0; |
|
|
tok->ucs_char = 0; |
|
|
tok->ucs_char = 0; |
|
|
tok->st_pos = 0; |
|
|
tok->st_pos = 0; |
|
@@ -820,7 +853,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
* Put a replacement char in for the high surrogate |
|
|
* Put a replacement char in for the high surrogate |
|
|
* and handle the escape sequence normally. |
|
|
* and handle the escape sequence normally. |
|
|
*/ |
|
|
*/ |
|
|
printbuf_memappend_fast(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, (char *)utf8_replacement_char, 3); |
|
|
tok->high_surrogate = 0; |
|
|
tok->high_surrogate = 0; |
|
|
tok->ucs_char = 0; |
|
|
tok->ucs_char = 0; |
|
|
tok->st_pos = 0; |
|
|
tok->st_pos = 0; |
|
@@ -835,7 +868,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
case json_tokener_state_boolean: |
|
|
case json_tokener_state_boolean: |
|
|
{ |
|
|
{ |
|
|
int size1, size2; |
|
|
int size1, size2; |
|
|
printbuf_memappend_fast(tok->pb, &c, 1); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, &c, 1); |
|
|
size1 = json_min(tok->st_pos + 1, json_true_str_len); |
|
|
size1 = json_min(tok->st_pos + 1, json_true_str_len); |
|
|
size2 = json_min(tok->st_pos + 1, json_false_str_len); |
|
|
size2 = json_min(tok->st_pos + 1, json_false_str_len); |
|
|
if ((!(tok->flags & JSON_TOKENER_STRICT) && |
|
|
if ((!(tok->flags & JSON_TOKENER_STRICT) && |
|
@@ -846,7 +879,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
current = json_object_new_boolean(1); |
|
|
current = json_object_new_boolean(1); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
saved_state = json_tokener_state_finish; |
|
|
saved_state = json_tokener_state_finish; |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
goto redo_char; |
|
|
goto redo_char; |
|
@@ -860,7 +896,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
current = json_object_new_boolean(0); |
|
|
current = json_object_new_boolean(0); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
saved_state = json_tokener_state_finish; |
|
|
saved_state = json_tokener_state_finish; |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
goto redo_char; |
|
|
goto redo_char; |
|
@@ -940,7 +979,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
|
|
|
|
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, case_len); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, case_len); |
|
|
goto out; |
|
|
goto out; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@@ -949,7 +988,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
it might have been intended to be, and return a potentially |
|
|
it might have been intended to be, and return a potentially |
|
|
more understandable error right away. |
|
|
more understandable error right away. |
|
|
However, if we're at the top-level, use the number as-is |
|
|
However, if we're at the top-level, use the number as-is |
|
|
because c can be part of a new object to parse on the |
|
|
|
|
|
|
|
|
because c can be part of a new object to parse on the |
|
|
next call to json_tokener_parse(). |
|
|
next call to json_tokener_parse(). |
|
|
*/ |
|
|
*/ |
|
|
if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' && |
|
|
if (tok->depth > 0 && c != ',' && c != ']' && c != '}' && c != '/' && |
|
@@ -959,7 +998,7 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
goto out; |
|
|
goto out; |
|
|
} |
|
|
} |
|
|
if (case_len > 0) |
|
|
if (case_len > 0) |
|
|
printbuf_memappend_fast(tok->pb, case_start, case_len); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, case_len); |
|
|
|
|
|
|
|
|
// Check for -Infinity |
|
|
// Check for -Infinity |
|
|
if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I')) |
|
|
if (tok->pb->buf[0] == '-' && case_len <= 1 && (c == 'i' || c == 'I')) |
|
@@ -999,7 +1038,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
} |
|
|
} |
|
|
current = json_object_new_int64(num64); |
|
|
current = json_object_new_int64(num64); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
else if (!tok->is_double && tok->pb->buf[0] != '-' && |
|
|
else if (!tok->is_double && tok->pb->buf[0] != '-' && |
|
|
json_parse_uint64(tok->pb->buf, &numuint64) == 0) |
|
|
json_parse_uint64(tok->pb->buf, &numuint64) == 0) |
|
@@ -1020,13 +1062,19 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
num64 = (uint64_t)numuint64; |
|
|
num64 = (uint64_t)numuint64; |
|
|
current = json_object_new_int64(num64); |
|
|
current = json_object_new_int64(num64); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
current = json_object_new_uint64(numuint64); |
|
|
current = json_object_new_uint64(numuint64); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (tok->is_double && |
|
|
else if (tok->is_double && |
|
@@ -1035,7 +1083,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
current = json_object_new_double_s(numd, tok->pb->buf); |
|
|
current = json_object_new_double_s(numd, tok->pb->buf); |
|
|
if (current == NULL) |
|
|
if (current == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
@@ -1080,7 +1131,10 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
|
|
|
|
|
|
case json_tokener_state_array_add: |
|
|
case json_tokener_state_array_add: |
|
|
if (json_object_array_add(current, obj) != 0) |
|
|
if (json_object_array_add(current, obj) != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
goto out; |
|
|
goto out; |
|
|
|
|
|
} |
|
|
saved_state = json_tokener_state_array_sep; |
|
|
saved_state = json_tokener_state_array_sep; |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
goto redo_char; |
|
|
goto redo_char; |
|
@@ -1140,25 +1194,30 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * |
|
|
{ |
|
|
{ |
|
|
if (c == tok->quote_char) |
|
|
if (c == tok->quote_char) |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
obj_field_name = strdup(tok->pb->buf); |
|
|
obj_field_name = strdup(tok->pb->buf); |
|
|
|
|
|
if (obj_field_name == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tok->err = json_tokener_error_memory; |
|
|
|
|
|
goto out; |
|
|
|
|
|
} |
|
|
saved_state = json_tokener_state_object_field_end; |
|
|
saved_state = json_tokener_state_object_field_end; |
|
|
state = json_tokener_state_eatws; |
|
|
state = json_tokener_state_eatws; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
else if (c == '\\') |
|
|
else if (c == '\\') |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
saved_state = json_tokener_state_object_field; |
|
|
saved_state = json_tokener_state_object_field; |
|
|
state = json_tokener_state_string_escape; |
|
|
state = json_tokener_state_string_escape; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) |
|
|
{ |
|
|
{ |
|
|
printbuf_memappend_fast(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
|
|
|
|
|
|
printbuf_memappend_checked(tok->pb, case_start, |
|
|
|
|
|
str - case_start); |
|
|
goto out; |
|
|
goto out; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|