summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Korczynski <david@adalogics.com>2023-11-27 16:19:56 +0000
committerEmanuele Torre <torreemanuele6@gmail.com>2023-11-28 20:36:59 +0100
commit44300e43101a7b937ac2f5cd482c9e9a9d262fdb (patch)
tree1e223516867772ec942d6d440a8d761f8e5592de /src
parent88f01a741c8d63c4d1b5bc3ef61520c6eb93edaa (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.h1
-rw-r--r--src/jv_parse.c43
2 files changed, 44 insertions, 0 deletions
diff --git a/src/jv.h b/src/jv.h
index eb313f8a..2cc63c79 100644
--- a/src/jv.h
+++ b/src/jv.h
@@ -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);
+}