mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
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>
This commit is contained in:
committed by
Emanuele Torre
parent
88f01a741c
commit
44300e4310
1
src/jv.h
1
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 *);
|
||||
|
@ -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);
|
||||
}
|
||||
|
29
tests/jq_fuzz_parse_extended.c
Normal file
29
tests/jq_fuzz_parse_extended.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jv.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
|
||||
if (size < 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fuzz_flags = *(int*)data;
|
||||
data += 4;
|
||||
size -= 4;
|
||||
|
||||
// Creat null-terminated string
|
||||
char *null_terminated = (char *)malloc(size + 1);
|
||||
memcpy(null_terminated, (char *)data, size);
|
||||
null_terminated[size] = '\0';
|
||||
|
||||
// Fuzzer entrypoint
|
||||
jv res = jv_parse_custom_flags(null_terminated, fuzz_flags);
|
||||
jv_free(res);
|
||||
|
||||
// Free the null-terminated string
|
||||
free(null_terminated);
|
||||
|
||||
return 0;
|
||||
}
|
21
tests/jq_fuzz_parse_stream.c
Normal file
21
tests/jq_fuzz_parse_stream.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jv.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
|
||||
// Creat null-terminated string
|
||||
char *null_terminated = (char *)malloc(size + 1);
|
||||
memcpy(null_terminated, (char *)data, size);
|
||||
null_terminated[size] = '\0';
|
||||
|
||||
// Fuzzer entrypoint
|
||||
jv res = jv_parse_custom_flags(null_terminated, JV_PARSE_STREAMING);
|
||||
jv_free(res);
|
||||
|
||||
// Free the null-terminated string
|
||||
free(null_terminated);
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user