diff --git a/eth/common/eth_types.nim b/eth/common/eth_types.nim index 6e96f6c..dca99da 100644 --- a/eth/common/eth_types.nim +++ b/eth/common/eth_types.nim @@ -329,7 +329,10 @@ proc rlpHash*[T](v: T): Hash256 = func blockHash*(h: BlockHeader): KeccakHash {.inline.} = rlpHash(h) proc notImplemented = - doAssert false, "Method not implemented" + when defined(afl) or defined(libFuzzer): + discard + else: + doAssert false, "Method not implemented" template hasData*(b: Blob): bool = b.len > 0 template hasData*(r: EthResourceRefs): bool = r != nil diff --git a/tests/fuzzing/config.nims b/tests/fuzzing/config.nims index ff37614..dfd3773 100644 --- a/tests/fuzzing/config.nims +++ b/tests/fuzzing/config.nims @@ -7,6 +7,7 @@ proc aflSwitches() = switch("out", "fuzz-afl") proc libFuzzerSwitches() = + switch("define", "libFuzzer") switch("noMain", "") switch("cc", "clang") switch("passC", "-fsanitize=fuzzer,address") diff --git a/tests/fuzzing/fuzz_helpers.nim b/tests/fuzzing/fuzz_helpers.nim index 94ee2a3..a65dc52 100644 --- a/tests/fuzzing/fuzz_helpers.nim +++ b/tests/fuzzing/fuzz_helpers.nim @@ -44,7 +44,7 @@ type clangFast = aflClangFast proc aflCompile*(target: string, c: Compiler) = - let aflOptions = &"-d:standalone -d:noSignalHandler {$c}" + let aflOptions = &"-d:afl -d:noSignalHandler {$c}" let compileCmd = &"nim c {defaultFlags} {aflOptions} {target.quoteShell()}" exec compileCmd @@ -66,7 +66,7 @@ proc aflExec*(target: string, inputDir: string, resultsDir: string, exec fuzzCmd proc libFuzzerCompile*(target: string) = - let libFuzzerOptions = &"--noMain {libFuzzerClang}" + let libFuzzerOptions = &"-d:libFuzzer --noMain {libFuzzerClang}" let compileCmd = &"nim c {defaultFlags} {libFuzzerOptions} {target.quoteShell()}" exec compileCmd diff --git a/tests/fuzzing/fuzztest.nim b/tests/fuzzing/fuzztest.nim index 847a13d..232b12d 100644 --- a/tests/fuzzing/fuzztest.nim +++ b/tests/fuzzing/fuzztest.nim @@ -3,7 +3,7 @@ import streams, posix, strutils, chronicles, macros, stew/ranges/ptr_arith template fuzz(body) = # For code we want to fuzz, SIGSEGV is needed on unwanted exceptions. # However, this is only needed when fuzzing with afl. - when defined(standalone): + when defined(afl): try: body except Exception as e: @@ -29,7 +29,7 @@ proc NimMain() {.importc: "NimMain".} # The default init, gets redefined when init template is used. template initImpl(): untyped = - when defined(standalone): + when not defined(libFuzzer): discard else: proc fuzzerInit(): cint {.exportc: "LLVMFuzzerInitialize".} = @@ -46,7 +46,7 @@ template init*(body: untyped) = ## For libFuzzer this will only be run once. So only put data which is ## stateless or make sure everything gets properply reset for each new run in ## the test block. - when defined(standalone): + when not defined(libFuzzer): template initImpl(): untyped = fuzz: `body` else: template initImpl() = @@ -64,7 +64,7 @@ template test*(body: untyped): untyped = ## contains the payload provided by the fuzzer. mixin initImpl initImpl() - when defined(standalone): + when not defined(libFuzzer): var payload {.inject.} = readStdin() fuzz: `body` @@ -76,8 +76,6 @@ template test*(body: untyped): untyped = `body` -# var aflClangFast {.importc: "__AFL_HAVE_MANUAL_CONTROL", noDecl.}: int - when defined(clangfast): ## Can be used for deferred instrumentation. ## Should be placed on a suitable location in the code where the delayed diff --git a/tests/fuzzing/readme.md b/tests/fuzzing/readme.md index b6b0fa3..2e29df0 100644 --- a/tests/fuzzing/readme.md +++ b/tests/fuzzing/readme.md @@ -92,9 +92,9 @@ nim fuzz.nims libFuzzer testcase.nim #### Compiling With gcc: ```sh -nim c -d:standalone -d:release -d:chronicles_log_level=fatal -d:noSignalHandler --cc=gcc --gcc.exe=afl-gcc --gcc.linkerexe=afl-gcc testcase.nim +nim c -d:afl -d:release -d:chronicles_log_level=fatal -d:noSignalHandler --cc=gcc --gcc.exe=afl-gcc --gcc.linkerexe=afl-gcc testcase.nim ``` -The `standalone` define is specifically required for the `init` and `test` +The `afl` define is specifically required for the `init` and `test` templates. You typically want to fuzz in `-d:release` and probably also want to lower down @@ -108,9 +108,9 @@ nim c build_afl testcase.nim With clang: ```sh # afl-clang -nim c -d:standalone -d:noSignalHandler --cc=clang --clang.exe=afl-clang --clang.linkerexe=afl-clang ftestcase.nim +nim c -d:afl -d:noSignalHandler --cc=clang --clang.exe=afl-clang --clang.linkerexe=afl-clang ftestcase.nim # afl-clang-fast -nim c -d:standalone -d:noSignalHandler --cc=clang --clang.exe=afl-clang-fast --clang.linkerexe=afl-clang-fast testcase.nim +nim c -d:afl -d:noSignalHandler --cc=clang --clang.exe=afl-clang-fast --clang.linkerexe=afl-clang-fast testcase.nim ``` #### Starting the Fuzzer @@ -135,17 +135,26 @@ afl-fuzz -i input -o results -S fuzzer03 -- ./testcase # add more if needed ``` -When compiled with `-d:standalone` the resulting application can also be run +When compiled with `-d:afl` the resulting application can also be run manually by providing it input data, e.g.: ```sh -cat testfile | ./testcase +./testcase < testfile ``` +During debugging you might not want the testcase to generate a segmentation +fault on exceptions. You can do this by rebuilding the test without the `-d:afl` +flag. Changing to `-d:debug` will also help but might also change the +behaviour. + ### Manually with libFuzzer #### Compiling ```sh -nim c -d:release -d:chronicles_log_level=fatal --noMain --cc=clang --passC="-fsanitize=fuzzer" --passL="-fsanitize=fuzzer" testcase.nim +nim c -d:libFuzzer -d:release -d:chronicles_log_level=fatal --noMain --cc=clang --passC="-fsanitize=fuzzer" --passL="-fsanitize=fuzzer" testcase.nim ``` + +The `libFuzzer` define is specifically required for the `init` and `test` +templates. + You typically want to fuzz in `-d:release` and probably also want to lower down the logging. But this is not strictly necessary. @@ -180,14 +189,16 @@ The `init` template, when used with **afl**, is only cosmetic. It will be run before each test block, compared to libFuzzer, where it will be run only once. -In case of using afl with `alf-clang-fast` you can make use of `aflInit()` and -`aflLoop()` calls. +In case of using afl with `alf-clang-fast` you can make use of `aflInit()` proc +and `aflLoop()` template. `aflInit()` will allow using what is called deferred instrumentation. Basically, the forking of the process will only happen after this call, where normally it is done right before `main()`. -`aflLoop(cint)` will allow for (experimental) persistant mode. This is more -comparable with libFuzzer. +`aflLoop:` will allow for (experimental) persistant mode. It will run the test +in loop (1000 iterations) with different payloads. This is more comparable with +libFuzzer. -These calls are enabled with `-d:clangfast`. +These calls are enabled with `-d:clangfast`, and have to be manually added. +They are currently not part of the `test` or `init` templates.