diff options
author | David Korczynski <david@adalogics.com> | 2023-11-27 16:19:56 +0000 |
---|---|---|
committer | Emanuele Torre <torreemanuele6@gmail.com> | 2023-11-28 20:36:59 +0100 |
commit | 44300e43101a7b937ac2f5cd482c9e9a9d262fdb (patch) | |
tree | 1e223516867772ec942d6d440a8d761f8e5592de /src | |
parent | 88f01a741c8d63c4d1b5bc3ef61520c6eb93edaa (diff) |
Extend fuzzing set up
Adds a parse function ins `jv_parse.c` that enables parsing using custom
flags for the parser. This is then used by two fuzzers added as well.
This is to make sure fuzzing hits various code parts currently not
fuzzed, e.g. `stream_token`:
https://storage.googleapis.com/oss-fuzz-coverage/jq/reports/20231125/linux/src/jq/src/jv_parse.c.html#L241
Signed-off-by: David Korczynski <david@adalogics.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/jv.h | 1 | ||||
-rw-r--r-- | src/jv_parse.c | 43 |
2 files changed, 44 insertions, 0 deletions
@@ -234,6 +234,7 @@ enum { jv jv_parse(const char* string); jv jv_parse_sized(const char* string, int length); +jv jv_parse_custom_flags(const char* string, int flags); typedef void (*jv_nomem_handler_f)(void *); void jv_nomem_handler(jv_nomem_handler_f, void *); diff --git a/src/jv_parse.c b/src/jv_parse.c index 3be93608..0c427eae 100644 --- a/src/jv_parse.c +++ b/src/jv_parse.c @@ -901,3 +901,46 @@ jv jv_parse_sized(const char* string, int length) { jv jv_parse(const char* string) { return jv_parse_sized(string, strlen(string)); } + +jv jv_parse_sized_custom_flags(const char* string, int length, int flags) { + struct jv_parser parser; + parser_init(&parser, flags); + jv_parser_set_buf(&parser, string, length, 0); + jv value = jv_parser_next(&parser); + if (jv_is_valid(value)) { + jv next = jv_parser_next(&parser); + if (jv_is_valid(next)) { + // multiple JSON values, we only wanted one + jv_free(value); + jv_free(next); + value = jv_invalid_with_msg(jv_string("Unexpected extra JSON values")); + } else if (jv_invalid_has_msg(jv_copy(next))) { + // parser error after the first JSON value + jv_free(value); + value = next; + } else { + // a single valid JSON value + jv_free(next); + } + } else if (jv_invalid_has_msg(jv_copy(value))) { + // parse error, we'll return it + } else { + // no value at all + jv_free(value); + value = jv_invalid_with_msg(jv_string("Expected JSON value")); + } + parser_free(&parser); + + if (!jv_is_valid(value) && jv_invalid_has_msg(jv_copy(value))) { + jv msg = jv_invalid_get_msg(value); + value = jv_invalid_with_msg(jv_string_fmt("%s (while parsing '%s')", + jv_string_value(msg), + string)); + jv_free(msg); + } + return value; +} + +jv jv_parse_custom_flags(const char* string, int flags) { + return jv_parse_sized_custom_flags(string, strlen(string), flags); +} |