New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add fuzz test #1157
Add fuzz test #1157
Conversation
@@ -52,14 +52,14 @@ find_package(clang) | |||
|
|||
if(NOT MSVC) | |||
find_library(LIBXML2 NAMES xml2 libxml2) | |||
if(${LIBXML2} STREQUAL "LIBXML2-NOTFOUND") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of the worst parts of the CMake language is that all *-NOTFOUND
strings evaluate to false.
src/fuzz_test.cpp
Outdated
@@ -0,0 +1,26 @@ | |||
#include <unistd.h> | |||
|
|||
#include "main.hpp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can #include "main.cpp"
here. That avoids a lot of churn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a bad idea but I'd have to conditionally rename main when fuzz test is selected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean this?
#define main not_real_main
#include "main.cpp"
#undef main
Seems acceptable to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
main.hpp can be dropped again now, can't it?
CMakeLists.txt
Outdated
if(BUILD_TESTING AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") | ||
add_executable(fuzz_test src/fuzz_test.cpp ${ZIG_SOURCES} ${ZIG_CPP_SOURCES}) | ||
target_compile_options(fuzz_test PRIVATE "-fsanitize=address,undefined,fuzzer") | ||
target_link_libraries(fuzz_test PRIVATE "-fsanitize=address,undefined,fuzzer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently failing with the xcode build, presumably because xcode doesn't have libFuzzer enabled:
/Applications/Xcode.app/Contents/Developer/usr/bin/g++ -I/Users/travis/build/ziglang/zig/deps/lld/include -I/usr/local/Cellar/llvm/6.0.0/include -I/usr/local/opt/llvm@6/include -I/Users/travis/build/ziglang/zig/deps/SoftFloat-3e/source/include -I/Users/travis/build/ziglang/zig -I/Users/travis/build/ziglang/zig/build -I/Users/travis/build/ziglang/zig/src -I/Users/travis/build/ziglang/zig/deps/SoftFloat-3e-prebuilt -I/Users/travis/build/ziglang/zig/deps/SoftFloat-3e/source/8086 -g -Wall -fsanitize=address,undefined,fuzzer -o CMakeFiles/fuzz_test.dir/src/fuzz_test.cpp.o -c /Users/travis/build/ziglang/zig/src/fuzz_test.cpp
clang: error: unsupported argument 'fuzzer' to option 'fsanitize='
Don't know about xcode 10 but with xcode 9, neither clang++ nor g++ understand -fsanitize=fuzzer
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mac aliases g++
to clang++
so they are actually the same compiler. Ironically, despite Apple's support for clang, Mac seems to be incapable of running the sanitizers/fuzzer by default. I know all about this because I have a Mac laptop.
src/fuzz_test.cpp
Outdated
perror("Cannot create temporary file"); | ||
return 0; | ||
} | ||
const int num_written = write(fd, data, size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use fdopen()
and fwrite()
since the latter takes care of retrying, but if you want to use write()
, handle EINTR:
ssize_t n;
do {
n = write(fd, data, size);
} while (n == -1 && errno == EINTR);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to know.
Yes I must have forgotten to delete it. Updated now. |
Why is Mac the only build in Travis CI? |
The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with some comments. Nice work!
CMakeLists.txt
Outdated
@@ -727,7 +726,7 @@ if(MSVC) | |||
elseif(MINGW) | |||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Werror -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args") | |||
else() | |||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -Wall") | |||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, why is it necessary to drop -Werror
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad. This was a local issue I needed to ignore momentarily. Will fix now.
CMakeLists.txt
Outdated
set(CMAKE_REQUIRED_FLAGS "${fuzzer_flags}") | ||
check_cxx_source_compiles(" | ||
#include <stdint.h> | ||
#include <stdlib.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for size_t, right? Technically, that's from stddef.h.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK ya the two headers are for size_t
and uint8_t
. Will try to replace stdlib
with stddef
.
src/fuzz_test.cpp
Outdated
|
||
char arg0[] = "zig"; | ||
char arg1[] = "build-obj"; | ||
char* argv[] = { arg0, arg1, tmp_file_name }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have a nullptr at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
src/fuzz_test.cpp
Outdated
perror("Cannot open file handle"); | ||
return 0; | ||
} | ||
const int num_written = fwrite(data, 1, size, f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use size_t
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks will do.
OK all-in-all the fuzz test isn't exactly useful at the moment. Had to remove address sanitizer to avoid crashing due to memory leaks (even
|
This is really neat. Thanks for showing me how to use LLVM's fuzz testing capabilities. That said, I don't think it's time to fuzz stage1 (the c++ compiler) yet. The syntax isn't fully locked in, and stage1 is only used to build the self hosted compiler. We have 88 open bugs, all more important than anything the fuzz tester finds in the stage1 tokenizer or parser. On the other hand, I'm going to start getting a well-defined Zig IR syntax going in the self hosted compiler and start creating IR-to-IR test cases. This would be a high impact area to do fuzz testing on. But we're not there yet. |
I agree because the fuzz test doesn't work much at the moment anyway. I'm glad I could demonstrate this, but I understand the issues. Closing until further notice. |
So far it is really easy to generate an error. A compiler that doesn't crash implies it shouldn't choke on bad input. Once the compiler is mature enough, this might make sense as part of the standard testing in Travis CI.