diff options
-rw-r--r-- | json_tokener.c | 23 | ||||
-rw-r--r-- | json_tokener.h | 22 | ||||
-rw-r--r-- | tests/test_parse.c | 11 | ||||
-rw-r--r-- | tests/test_parse.expected | 4 |
4 files changed, 55 insertions, 5 deletions
diff --git a/json_tokener.c b/json_tokener.c index 6d50bc2..b2b47f9 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -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; +} diff --git a/json_tokener.h b/json_tokener.h index 3da520a..08e5ff7 100644 --- a/json_tokener.h +++ b/json_tokener.h @@ -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,9 +82,22 @@ 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; diff --git a/tests/test_parse.c b/tests/test_parse.c index 481cb12..1a59a6b 100644 --- a/tests/test_parse.c +++ b/tests/test_parse.c @@ -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) diff --git a/tests/test_parse.expected b/tests/test_parse.expected index 814dc62..f0af0fa 100644 --- a/tests/test_parse.expected +++ b/tests/test_parse.expected @@ -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 ================================== |