tests: add libFuzzer based tests
LibFuzzer is in-process, coverage-guided, evolutionary fuzzing engine. LibFuzzer is linked with the library under test, and feeds fuzzed inputs to the library via a specific fuzzing entrypoint (aka "target function"); the fuzzer then tracks which areas of the code are reached, and generates mutations on the corpus of input data in order to maximize the code coverage. Lets use libFuzzer to fuzz blob and blobmsg parsing for the start. Ref: https://llvm.org/docs/LibFuzzer.html Signed-off-by: Petr Štetiar <ynezz@true.cz>
This commit is contained in:
parent
bf680707ac
commit
436d6363a1
7 changed files with 99 additions and 0 deletions
|
@ -12,3 +12,7 @@ FOREACH(test_case ${test_cases})
|
|||
ADD_UNIT_TEST(${test_case})
|
||||
ADD_UNIT_TEST_SAN(${test_case})
|
||||
ENDFOREACH(test_case)
|
||||
|
||||
IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
ADD_SUBDIRECTORY(fuzz)
|
||||
ENDIF()
|
||||
|
|
18
tests/fuzz/CMakeLists.txt
Normal file
18
tests/fuzz/CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
FILE(GLOB test_cases "test-*.c")
|
||||
|
||||
MACRO(ADD_FUZZER_TEST name)
|
||||
ADD_EXECUTABLE(${name} ${name}.c)
|
||||
TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined)
|
||||
TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
|
||||
TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined)
|
||||
TARGET_LINK_LIBRARIES(${name} ubox blobmsg_json json_script ${json})
|
||||
ADD_TEST(
|
||||
NAME ${name}
|
||||
COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus
|
||||
)
|
||||
ENDMACRO(ADD_FUZZER_TEST)
|
||||
|
||||
FOREACH(test_case ${test_cases})
|
||||
GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
|
||||
ADD_FUZZER_TEST(${test_case})
|
||||
ENDFOREACH(test_case)
|
BIN
tests/fuzz/corpus/71520a5c4b5ca73903216857abbad54a8002d44a
Normal file
BIN
tests/fuzz/corpus/71520a5c4b5ca73903216857abbad54a8002d44a
Normal file
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
6
|
BIN
tests/fuzz/corpus/c42ac1c46f1d4e211c735cc7dfad4ff8391110e9
Normal file
BIN
tests/fuzz/corpus/c42ac1c46f1d4e211c735cc7dfad4ff8391110e9
Normal file
Binary file not shown.
BIN
tests/fuzz/corpus/valid-blobmsg.bin
Normal file
BIN
tests/fuzz/corpus/valid-blobmsg.bin
Normal file
Binary file not shown.
76
tests/fuzz/test-fuzz.c
Normal file
76
tests/fuzz/test-fuzz.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "blob.h"
|
||||
#include "blobmsg.h"
|
||||
|
||||
static void fuzz_blobmsg_parse(const uint8_t *data, size_t size)
|
||||
{
|
||||
enum {
|
||||
FOO_MESSAGE,
|
||||
FOO_LIST,
|
||||
FOO_TESTDATA,
|
||||
__FOO_MAX
|
||||
};
|
||||
|
||||
static const struct blobmsg_policy foo_policy[] = {
|
||||
[FOO_MESSAGE] = {
|
||||
.name = "message",
|
||||
.type = BLOBMSG_TYPE_STRING,
|
||||
},
|
||||
[FOO_LIST] = {
|
||||
.name = "list",
|
||||
.type = BLOBMSG_TYPE_ARRAY,
|
||||
},
|
||||
[FOO_TESTDATA] = {
|
||||
.name = "testdata",
|
||||
.type = BLOBMSG_TYPE_TABLE,
|
||||
},
|
||||
};
|
||||
|
||||
struct blob_attr *tb[__FOO_MAX];
|
||||
|
||||
blobmsg_parse(foo_policy, __FOO_MAX, tb, (uint8_t *)data, size);
|
||||
blobmsg_parse_array(foo_policy, __FOO_MAX, tb, (uint8_t *)data, size);
|
||||
}
|
||||
|
||||
static void fuzz_blob_parse(const uint8_t *data, size_t size)
|
||||
{
|
||||
enum {
|
||||
FOO_ATTR_NESTED,
|
||||
FOO_ATTR_BINARY,
|
||||
FOO_ATTR_STRING,
|
||||
FOO_ATTR_INT8,
|
||||
FOO_ATTR_INT16,
|
||||
FOO_ATTR_INT32,
|
||||
FOO_ATTR_INT64,
|
||||
FOO_ATTR_DOUBLE,
|
||||
__FOO_ATTR_MAX
|
||||
};
|
||||
|
||||
|
||||
static const struct blob_attr_info foo_policy[__FOO_ATTR_MAX] = {
|
||||
[FOO_ATTR_NESTED] = { .type = BLOB_ATTR_NESTED },
|
||||
[FOO_ATTR_BINARY] = { .type = BLOB_ATTR_BINARY },
|
||||
[FOO_ATTR_STRING] = { .type = BLOB_ATTR_STRING },
|
||||
[FOO_ATTR_INT8] = { .type = BLOB_ATTR_INT8 },
|
||||
[FOO_ATTR_INT16] = { .type = BLOB_ATTR_INT16 },
|
||||
[FOO_ATTR_INT32] = { .type = BLOB_ATTR_INT32 },
|
||||
[FOO_ATTR_INT64] = { .type = BLOB_ATTR_INT64 },
|
||||
[FOO_ATTR_DOUBLE] = { .type = BLOB_ATTR_DOUBLE },
|
||||
};
|
||||
|
||||
struct blob_attr *foo[__FOO_ATTR_MAX];
|
||||
struct blob_attr *buf = (struct blob_attr *)data;
|
||||
|
||||
blob_parse(buf, foo, foo_policy, __FOO_ATTR_MAX);
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
fuzz_blob_parse(data, size);
|
||||
fuzz_blobmsg_parse(data, size);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue