| @@ -624,8 +624,15 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| } | } | ||||
| break; | break; | ||||
| case json_tokener_state_array_after_sep: | |||||
| case json_tokener_state_array: | case json_tokener_state_array: | ||||
| if(c == ']') { | 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; | saved_state = json_tokener_state_finish; | ||||
| state = json_tokener_state_eatws; | state = json_tokener_state_eatws; | ||||
| } else { | } else { | ||||
| @@ -651,7 +658,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| saved_state = json_tokener_state_finish; | saved_state = json_tokener_state_finish; | ||||
| state = json_tokener_state_eatws; | state = json_tokener_state_eatws; | ||||
| } else if(c == ',') { | } else if(c == ',') { | ||||
| saved_state = json_tokener_state_array; | |||||
| saved_state = json_tokener_state_array_after_sep; | |||||
| state = json_tokener_state_eatws; | state = json_tokener_state_eatws; | ||||
| } else { | } else { | ||||
| tok->err = json_tokener_error_parse_array; | tok->err = json_tokener_error_parse_array; | ||||
| @@ -660,7 +667,14 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| break; | break; | ||||
| case json_tokener_state_object_field_start: | case json_tokener_state_object_field_start: | ||||
| case json_tokener_state_object_field_start_after_sep: | |||||
| if(c == '}') { | 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; | saved_state = json_tokener_state_finish; | ||||
| state = json_tokener_state_eatws; | state = json_tokener_state_eatws; | ||||
| } else if (c == '"' || c == '\'') { | } 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; | saved_state = json_tokener_state_finish; | ||||
| state = json_tokener_state_eatws; | state = json_tokener_state_eatws; | ||||
| } else if(c == ',') { | } 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; | state = json_tokener_state_eatws; | ||||
| } else { | } else { | ||||
| tok->err = json_tokener_error_parse_object_value_sep; | 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); | json_tokener_errors[tok->err], tok->char_offset); | ||||
| return NULL; | 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_field_end, | ||||
| json_tokener_state_object_value, | json_tokener_state_object_value, | ||||
| json_tokener_state_object_value_add, | 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 | struct json_tokener_srec | ||||
| @@ -80,8 +82,21 @@ struct json_tokener | |||||
| unsigned int ucs_char; | unsigned int ucs_char; | ||||
| char quote_char; | char quote_char; | ||||
| struct json_tokener_srec *stack; | 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(), | * Given an error previously returned by json_tokener_get_error(), | ||||
| * return a human readable description of the 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(const char *str); | ||||
| extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error); | 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 | * 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; | * 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, -1, json_tokener_success, 0 }, | ||||
| { "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 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 }, | { NULL, -1, -1, json_tokener_success, 0 }, | ||||
| }; | }; | ||||
| @@ -215,6 +218,12 @@ static void test_incremental_parse() | |||||
| struct incremental_step *step = &incremental_steps[ii]; | struct incremental_step *step = &incremental_steps[ii]; | ||||
| int length = step->length; | int length = step->length; | ||||
| int expected_char_offset = step->char_offset; | 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) | if (length == -1) | ||||
| length = strlen(step->string_to_parse); | length = strlen(step->string_to_parse); | ||||
| if (expected_char_offset == -1) | if (expected_char_offset == -1) | ||||
| @@ -264,7 +273,7 @@ static void test_incremental_parse() | |||||
| if (new_obj) | if (new_obj) | ||||
| json_object_put(new_obj); | json_object_put(new_obj); | ||||
| if (step->reset_tokener) | |||||
| if (step->reset_tokener & 1) | |||||
| json_tokener_reset(tok); | json_tokener_reset(tok); | ||||
| if (this_step_ok) | 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] , 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,] , 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 | 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 | |||||
| ================================== | ================================== | ||||