From d9ea7354530d16b269a5c5707946d6c09186fb75 Mon Sep 17 00:00:00 2001 From: niv Date: Fri, 20 Jan 2017 21:43:17 +0100 Subject: [PATCH] Updated Fuzzing your nim code to rabbit out all the hard bugs (markdown) --- ...im-code-to-rabbit-out-all-the-hard-bugs.md | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/Fuzzing-your-nim-code-to-rabbit-out-all-the-hard-bugs.md b/Fuzzing-your-nim-code-to-rabbit-out-all-the-hard-bugs.md index 14bc90a..70c60a1 100644 --- a/Fuzzing-your-nim-code-to-rabbit-out-all-the-hard-bugs.md +++ b/Fuzzing-your-nim-code-to-rabbit-out-all-the-hard-bugs.md @@ -44,35 +44,32 @@ except: This is a pretty contrived thing, but just imagine this being somewhere in a file reader or network parser, or anything like that. Now, nim in debug mode will catch some of the issues you can probably spot immediately, but let's assume the code is complex enough to confound you into missing them all. +The general idea is to boil down your testcase to just the code path you want to test; like part file handling library. The smaller, the faster; and the faster, the less time you have to wait for it to find all those eye-opening bugs you never thought of. + ## Make it work with afl -Save that example in a file called "afl.nim". Because afl needs to instrument the generated binary code, you need to tell nim to use the compiler frontend afl comes with, instead of whatever your distro defaults to. Create a file called "afl.nim.cfg" in the same directory and put this in: +Save that example in a file called **afltestcase.nim**. Because afl needs to instrument the generated binary code, you need to tell nim to use the compiler frontend afl comes with, instead of whatever your distro defaults to. Create a file called **afltestcase.nim.cfg** in the same directory and put this in: ```ini # nim.cfg for afl-clang -d:noSignalHandler + +# for OSX/homebrew cc = clang clang.exe = "afl-clang" clang.linkerexe = "afl-clang" clang.path = "/usr/local/Cellar/afl-fuzz/2.36b/bin" -``` -This is a working example for OSX, where afl was installed via homebrew. To make it work on any Linux, simply adjust clang.path. This will tell nim to use afl to compile afl.nim, instead of whatever your distro defaults to. - -Very important: `-d:noSignalHandler`, because AFL installs it's own signal handler inside instrumented code. - -```ini -# nim.cfg for afl-gcc --d:noSignalHandler +# OR for linux/debian (apt install afl) cc = gcc gcc.exe = "afl-gcc" gcc.linkerexe = "afl-gcc" ``` -This is a working example for Linux. AFL was installed globally with 'apt-get install afl' +This will tell nim to use afl to compile afltestcase.nim (and only that file, not any others!), instead of whatever your distro defaults to. Now, compile it: ``` -$ nim c -d:noSignalHandler afl +$ nim c afltestcase ``` You should see some output from afl confirming that it instrumented your binary properly, like: @@ -84,12 +81,12 @@ afl-cc 2.36b by ## Testcases -afl best works when given a bunch of valid testcases. It *can* make up random data, but if you have some idea of what working input looks like, it'll help speed things up: +afl best works when given a bunch of valid test data. It *can* make up random data, but if you have some idea of what working input looks like, it'll help speed things up: ``` $ mkdir afl-in/ -$ echo "\x03\02hi\05there\x03nim\x03\x02\x01\x00" >! afl-in/testdata -$ ./afl < afl-in/testdata +$ echo "\x03\02hi\05there\x03nim\x03\x02\x01\x00" > afl-in/testdata +$ ./afltestcase < afl-in/testdata Read 3 texts Read 3 picks 2=nim @@ -106,12 +103,12 @@ Finally, we can run afl. As afl feeds it's mutating input on stdin by default, w ``` $ mkdir afl-out/ -$ afl-fuzz -i afl-in/ -o afl-out/ -- ./afl +$ afl-fuzz -i afl-in/ -o afl-out/ -- ./afltestcase ``` Let it run for a while, but it should start finding issues pretty much immediately. While crash triage is way out of scope of this document, it should give you something to start - as soon as it starts finding crashes or hangs, look into afl-out/crashes|hangs for the input data that made your code throw an exception or hang: ``` -$ ./afl < afl-out/crashes/id:000000,sig:11,src:000000,op:flip1,pos:0 +$ ./afltestcase < afl-out/crashes/id:000000,sig:11,src:000000,op:flip1,pos:0 Read 0 texts Read 2 picks ref 0x10f911050 --> [parent = nil,