Originally, the sanitizer infrastructure was developed to work within the
clang compiler built on top of
LLVM.
Thankfully, these options are now available for gcc as well.
Just replace clang in any of the invocations below with gcc.
java -jar $FINDBUGS_HOME/lib/findbugs.jar
Simply add the jar and/or class files through the GUI interface.
CBMC
For a simple comparison with the clang static analyzer: scan-build vg1.c cbmc --bounds-check --pointer-check vg1.c cbmc --bounds-check --pointer-check vg4.c
And showing the pitfalls of loops: cbmc binsearch.c --function binsearch --bounds-check cbmc binsearch.c --function binsearch --unwind 6 --bounds-check
See also LLBMC for bounded model checking of programs
compiled by clang/LLVM.
Managing False Positives
Suppression
Dynamic analysis tools usually have some mechanism of error suppression.
Users can specify suppression criteria, and any warning that matches these
criteria can be prevented.
In Valgrind
You can generate suppression criteria for all warnings in an execution via the
--gen-suppressions=all option and capture the output using --log-file: valgrind --gen-suppressions=all --log-file=suppressionfile ./a.out
Edit this file to match only the warnings you recognize as false positives.
You can then use the suppression file to avoid warnings in the future. valgrind --suppressions=suppressionfile ./a.out
In Clang Sanitizers
All Clang Sanitizers support special case lists / blacklists of errors that
ought to be suppressed. Given a particular suppression file, the suppressions
are used at compile time via the -fsanitize-blacklist= option: clang -g -fsanitize=address -fsanitize-blacklist=blacklist.txt vg2.c
The static analyzer learns about potential bugs based on the the analyzed code.
Thus, to avoid false positives, you can either add assertions to the code or
remove unnecessary statements that imply potentially bad behavior.
In more extreme cases, annotations may be helpful.
American Fuzzy Lop, or AFL, uses compile time instrumentation to perform more
intelligent fuzzing than simple black box testing would allow. In order to start
using AFL, you first need to download the tool, build it, and configure your
environment:
1
2
3
4
5
git clone https://github.com/AFLplusplus/AFLplusplus
cd AFL<TAB>
make source-only
export PATH=$PATH:`pwd`
export AFL_PATH=`pwd`
And enable core dumps via:
1
echo core > /proc/sys/kernel/core_pattern
or on Ubuntu:
1
sudo service apport stop
Once you have done this once, you can just configure your environment again
using the last three lines the next time that you log into your machine.
afl-gcc afl.c
mkdir in out
echo ssssdwdsd > in/seed
AFL_SKIP_CPUFREQ=1 afl-fuzz -o out -i in -- ./a.out
A more complicated/realistic project will require you to integrate the afl-fuzz
compiler into the build system of the project itself.For instance, the following
will fuzz test indent using its regression
tests as input seeds.
1
2
3
4
5
CC=afl-gcc CXX=afl-g++ ./configure --disable-shared
AFL_HARDEN=1 make clean all
mkdir in out
cp regression/*.c in/
AFL_SKIP_CPUFREQ=1 afl-fuzz -i in/ -o out/ -t 10000 src/indent -st @@
These examples assume that you are using the Docker
image for KLEE, available
here. The examples are drawn from the original
KLEE tutorials as well as
blog posts
that walk through them in greater detail. You can start an instance of the KLEE
Docker image with one of your paths mapped/mounted inside the instance via:
docker run -ti --name=<instance name> --ulimit='stack=-1:-1' -v <path/in/filesystem>:</path/in/instance> klee/klee
In this case, we are testing the get_sign() function, and we include a
main() that acts as a test driver