diff --git a/libchewing/Dockerfile b/libchewing/Dockerfile index 389edaadd..b3625028c 100644 --- a/libchewing/Dockerfile +++ b/libchewing/Dockerfile @@ -19,4 +19,4 @@ MAINTAINER kcwu@csie.org RUN apt-get install -y make autoconf automake libtool texinfo RUN git clone https://github.com/chewing/libchewing.git -COPY build.sh chewing_fuzzer.c /src/ +COPY build.sh chewing_fuzzer_common.[ch] chewing_*_fuzzer.c /src/ diff --git a/libchewing/build.sh b/libchewing/build.sh index b6fab1bc6..a4db16794 100755 --- a/libchewing/build.sh +++ b/libchewing/build.sh @@ -25,11 +25,13 @@ make clean all # build your fuzzer(s) make -C test CFLAGS="$CFLAGS -Dmain=stress_main -Drand=get_fuzz_input" stress.o -$CC $CFLAGS \ - -o /out/chewing_fuzzer \ - /src/chewing_fuzzer.c \ - test/stress.o test/.libs/libtesthelper.a src/.libs/libchewing.a \ - -lfuzzer $FUZZER_LDFLAGS +for variant in default random_init dynamic_config; do + $CC $CFLAGS \ + -o /out/chewing_${variant}_fuzzer \ + /src/chewing_${variant}_fuzzer.c /src/chewing_fuzzer_common.c \ + test/stress.o test/.libs/libtesthelper.a src/.libs/libchewing.a \ + -lfuzzer $FUZZER_LDFLAGS +done # install data files make -C data pkgdatadir=/out install diff --git a/libchewing/chewing_default_fuzzer.c b/libchewing/chewing_default_fuzzer.c new file mode 100644 index 000000000..dd6fc7a84 --- /dev/null +++ b/libchewing/chewing_default_fuzzer.c @@ -0,0 +1,15 @@ +#include + +#include "chewing_fuzzer_common.h" + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + fuzz_input = fuzz_ptr = data; + fuzz_size = size; + + const char* stress_argv[] = { + "./chewing_fuzzer", "-loop", "1", NULL, + }; + stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1, + (char**)stress_argv); + return 0; +} diff --git a/libchewing/chewing_dynamic_config_fuzzer.c b/libchewing/chewing_dynamic_config_fuzzer.c new file mode 100644 index 000000000..5479c1ee1 --- /dev/null +++ b/libchewing/chewing_dynamic_config_fuzzer.c @@ -0,0 +1,15 @@ +#include + +#include "chewing_fuzzer_common.h" + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + fuzz_input = fuzz_ptr = data; + fuzz_size = size; + + const char* stress_argv[] = { + "./chewing_fuzzer", "-loop", "1", "-extra", NULL, + }; + stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1, + (char**)stress_argv); + return 0; +} diff --git a/libchewing/chewing_fuzzer.c b/libchewing/chewing_fuzzer.c deleted file mode 100644 index e7b6e610d..000000000 --- a/libchewing/chewing_fuzzer.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include -#include -#include - -static const uint8_t* fuzz_ptr; -static const uint8_t* fuzz_input; -static size_t fuzz_size; - -int stress_main(int argc, char** argv); - - int LLVMFuzzerInitialize(int* argc, char*** argv) { - char* exe_path = (*argv)[0]; - char* dir = dirname(exe_path); - // Assume data files are at the same location as executable. - setenv("CHEWING_PATH", dir, 0); - setenv("CHEWING_USER_PATH", "/tmp", 0); - return 0; - } - -int get_fuzz_input() { - if (fuzz_ptr - fuzz_input >= fuzz_size) - return EOF; - return *fuzz_ptr++; -} - -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - fuzz_input = fuzz_ptr = data; - fuzz_size = size; - - const char *stress_argv[] = { - "./chewing_fuzzer", - "-extra", - "-loop", "1", - NULL, - }; - stress_main(4, (char**)stress_argv); - return 0; -} diff --git a/libchewing/chewing_fuzzer_common.c b/libchewing/chewing_fuzzer_common.c new file mode 100644 index 000000000..de249df67 --- /dev/null +++ b/libchewing/chewing_fuzzer_common.c @@ -0,0 +1,26 @@ +#include "chewing_fuzzer_common.h" + +#include +#include +#include + +static char userphrase_path[] = "/tmp/chewing_userphrase.db.XXXXXX"; + +int LLVMFuzzerInitialize(int* argc, char*** argv) { + char* exe_path = (*argv)[0]; + char* dir = dirname(exe_path); + // Assume data files are at the same location as executable. + setenv("CHEWING_PATH", dir, 0); + + // Specify user db of this process. So we can run multiple fuzzers at the + // same time. + mktemp(userphrase_path); + setenv("TEST_USERPHRASE_PATH", userphrase_path, 0); + return 0; +} + +int get_fuzz_input() { + if (fuzz_ptr - fuzz_input >= fuzz_size) + return EOF; + return *fuzz_ptr++; +} diff --git a/libchewing/chewing_fuzzer_common.h b/libchewing/chewing_fuzzer_common.h new file mode 100644 index 000000000..5032d655c --- /dev/null +++ b/libchewing/chewing_fuzzer_common.h @@ -0,0 +1,13 @@ +#ifndef CHEWING_FUZZER_COMMON_H +#define CHEWING_FUZZER_COMMON_H + +#include +#include + +const uint8_t* fuzz_ptr; +const uint8_t* fuzz_input; +size_t fuzz_size; + +int stress_main(int argc, char** argv); + +#endif diff --git a/libchewing/chewing_random_init_fuzzer.c b/libchewing/chewing_random_init_fuzzer.c new file mode 100644 index 000000000..3e6a841b5 --- /dev/null +++ b/libchewing/chewing_random_init_fuzzer.c @@ -0,0 +1,15 @@ +#include + +#include "chewing_fuzzer_common.h" + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + fuzz_input = fuzz_ptr = data; + fuzz_size = size; + + const char* stress_argv[] = { + "./chewing_fuzzer", "-loop", "1", "-init", "-extra", NULL, + }; + stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1, + (char**)stress_argv); + return 0; +}