@@ -624,8 +624,15 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
} | |||
break; | |||
case json_tokener_state_array_after_sep: | |||
case json_tokener_state_array: | |||
if(c == ']') { | |||
if (state == json_tokener_state_array_after_sep && | |||
(tok->flags & JSON_TOKENER_STRICT)) | |||
{ | |||
tok->err = json_tokener_error_parse_unexpected; | |||
goto out; | |||
} | |||
saved_state = json_tokener_state_finish; | |||
state = json_tokener_state_eatws; | |||
} else { | |||
@@ -651,7 +658,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
saved_state = json_tokener_state_finish; | |||
state = json_tokener_state_eatws; | |||
} else if(c == ',') { | |||
saved_state = json_tokener_state_array; | |||
saved_state = json_tokener_state_array_after_sep; | |||
state = json_tokener_state_eatws; | |||
} else { | |||
tok->err = json_tokener_error_parse_array; | |||
@@ -660,7 +667,14 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
break; | |||
case json_tokener_state_object_field_start: | |||
case json_tokener_state_object_field_start_after_sep: | |||
if(c == '}') { | |||
if (state == json_tokener_state_object_field_start_after_sep && | |||
(tok->flags & JSON_TOKENER_STRICT)) | |||
{ | |||
tok->err = json_tokener_error_parse_unexpected; | |||
goto out; | |||
} | |||
saved_state = json_tokener_state_finish; | |||
state = json_tokener_state_eatws; | |||
} else if (c == '"' || c == '\'') { | |||
@@ -731,7 +745,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
saved_state = json_tokener_state_finish; | |||
state = json_tokener_state_eatws; | |||
} else if(c == ',') { | |||
saved_state = json_tokener_state_object_field_start; | |||
saved_state = json_tokener_state_object_field_start_after_sep; | |||
state = json_tokener_state_eatws; | |||
} else { | |||
tok->err = json_tokener_error_parse_object_value_sep; | |||
@@ -771,3 +785,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||
json_tokener_errors[tok->err], tok->char_offset); | |||
return NULL; | |||
} | |||
void json_tokener_set_flags(struct json_tokener *tok, int flags) | |||
{ | |||
tok->flags = flags; | |||
} |
@@ -58,7 +58,9 @@ enum json_tokener_state { | |||
json_tokener_state_object_field_end, | |||
json_tokener_state_object_value, | |||
json_tokener_state_object_value_add, | |||
json_tokener_state_object_sep | |||
json_tokener_state_object_sep, | |||
json_tokener_state_array_after_sep, | |||
json_tokener_state_object_field_start_after_sep | |||
}; | |||
struct json_tokener_srec | |||
@@ -80,8 +82,21 @@ struct json_tokener | |||
unsigned int ucs_char; | |||
char quote_char; | |||
struct json_tokener_srec *stack; | |||
int flags; | |||
}; | |||
/** | |||
* Be strict when parsing JSON input. Use caution with | |||
* this flag as what is considered valid may become more | |||
* restrictive from one release to the next, causing your | |||
* code to fail on previously working input. | |||
* | |||
* This flag is not set by default. | |||
* | |||
* @see json_tokener_set_flags() | |||
*/ | |||
#define JSON_TOKENER_STRICT 0x01 | |||
/** | |||
* Given an error previously returned by json_tokener_get_error(), | |||
* return a human readable description of the error. | |||
@@ -116,6 +131,11 @@ extern void json_tokener_reset(struct json_tokener *tok); | |||
extern struct json_object* json_tokener_parse(const char *str); | |||
extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error); | |||
/** | |||
* Set flags that control how parsing will be done. | |||
*/ | |||
extern void json_tokener_set_flags(struct json_tokener *tok, int flags); | |||
/** | |||
* Parse a string and return a non-NULL json_object if a valid JSON value | |||
* is found. The string does not need to be a JSON object or array; | |||
@@ -183,6 +183,9 @@ struct incremental_step { | |||
{ "[1,2,3,]", -1, -1, json_tokener_success, 0 }, | |||
{ "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 }, | |||
{ "[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 3 }, | |||
{ "{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 3 }, | |||
{ NULL, -1, -1, json_tokener_success, 0 }, | |||
}; | |||
@@ -215,6 +218,12 @@ static void test_incremental_parse() | |||
struct incremental_step *step = &incremental_steps[ii]; | |||
int length = step->length; | |||
int expected_char_offset = step->char_offset; | |||
if (step->reset_tokener & 2) | |||
json_tokener_set_flags(tok, JSON_TOKENER_STRICT); | |||
else | |||
json_tokener_set_flags(tok, 0); | |||
if (length == -1) | |||
length = strlen(step->string_to_parse); | |||
if (expected_char_offset == -1) | |||
@@ -264,7 +273,7 @@ static void test_incremental_parse() | |||
if (new_obj) | |||
json_object_put(new_obj); | |||
if (step->reset_tokener) | |||
if (step->reset_tokener & 1) | |||
json_tokener_reset(tok); | |||
if (this_step_ok) | |||
@@ -51,5 +51,7 @@ json_tokener_parse_ex(tok, "\t" , 4) ... OK: got object of type [string | |||
json_tokener_parse_ex(tok, [1,2,3] , 7) ... OK: got object of type [array]: [ 1, 2, 3 ] | |||
json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array]: [ 1, 2, 3 ] | |||
json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character | |||
End Incremental Tests OK=27 ERROR=0 | |||
json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got correct error: unexpected character | |||
json_tokener_parse_ex(tok, {"a":1,} , 8) ... OK: got correct error: unexpected character | |||
End Incremental Tests OK=29 ERROR=0 | |||
================================== |