On this page we show you how to use Oink/Cqual++ to find printf format string bugs in your code as soon as possible. You can do other things with Oink as well, but we want to show you the end-to-end process of doing one useful thing right away. Some of this information is redundant with that of the main Oink page; I repeat it so these instructions would be self-contained. You need to do the following.
You can get the latest tarball release. However I suggest instead that you get oink directly from the subversion repository; everything you need is actually in one single container repository called oink-stack. You will need an ssl-enabled subversion client. NOTE: We have a report that TortoiseSVN is not working; use the command-line svn utility.
svn checkout https://svn.cubewano.org/repos/oink-stack/trunk oink-stack
To build everything, in oink-stack/ type:
./configure && make clean all check
Upon successful build, you should see
================================================================
DONE in all directories: check
================================================================
If you have problems with the platform-model tests failing with a segmentation fault, this seems to often be due to problems with libzipios++ and zlib. Make sure that your version of these libraries was built with the same version of the compiler that you are building Oink with. Another solution is to just turn off zip archiving, falling back to a more primitive method. Do this from the oink-stack directory as follows.
./configure +platform-model:--archive-srz=dir +oink:-require-no-archive-srz-zip
Oink works on files that have been through the preprocessor, usually known as .i files. You have to get these files from the build process of your project somehow. If your project has a simple build process and uses gcc, you can do this by just adding -save-temps to the compile flags, which we will use here. For industrial-strength build process interception of any build process using gcc you may want to use build-interceptor.
For demonstration purposes I have written a really simple example project in oink-stack/oink/Test/Quickstart1/. All of the changes to the makefile needed to produce the .i files amount to these as follows.
TOCLEAN += *.i *.s CFLAGS += -save-temps
Here it the build process in action.
cd /home/dsw/oink-stack/oink/Test/Quickstart1/ make clean all check rm -f *.i *.s *.o hello cc -save-temps -c -o main.o main.c cc -save-temps -c -o g.o g.c cc -o hello main.o g.o Testing. HELLO='good data' ./hello Hello, World! The important data is good data HELLO='evil data' ./hello Hello, World! The important data is evil data
We now want to run Oink/Cqual++, oink-stack/oink/qual, on the .i files. In general, to learn more about what Oink/Cqual++ it can do, see the Cqual++ documentation; for more on its command line flags, type oink-stack/oink/qual --help.
To illustrate how to get started, I have added to the oink-stack/oink/Test/Quickstart1/Makefile a section just to do this for you.
OINK_STACK := ../../.. .PHONY: analyze analyze: all $(OINK_STACK)/oink-scripts/bin/qualx main.i g.i -lc
Here it is in action. Note that the total time includes loading the libc dataflow model, so Cqual++ will seem rather slow for analyzing such a tiny program; I talk about this below.
cd /home/dsw/oink-stack/oink/Test/Quickstart1/ make analyze ../../../oink-scripts/bin/qualx main.i g.i -lc Reporting 4 of 4 errors (including anonymous) . . . (skipping duplicate errors) . . . main.i:1823 WARNING (4 of 4): ( (getenv) ( ("HELLO")))' treated as $tainted and $untainted ( (getenv) ( ("HELLO")))': $tainted $untainted /home/dsw/oink-stack/platform-model/libc_glibc-2.3.5/src/stdlib.qual.i:2178:15: $tainted <= t149145-char main.i:1631:13: <= getenv_ret' main.i:1823:3: <= ( (getenv) ( ("HELLO")))' main.i:1823:3: <= data'' main.i:1824:3: <= t5117-char main.i:1815:6: <= t5117-char main.i:1815:6: <= data'' main.i:1817:5: <= t1628-char main.i:10:6: <= t6740-char g.i:918:6: <= t8488-char g.i:918:6: <= data'' g.i:920:3: <= const t7909-char g.i:644:12: <= const t85944-char /home/dsw/oink-stack/platform-model/libc_glibc-2.3.5/src/stdio.qual.i:1990:5: <= $untainted make: *** [analyze] Error 32
As you can see, Cqual++ is showing you a dataflow path from $tainted to $untainted; note that the output format is designed so that in emacs compile mode, C-x backtick should take you from one line to the next. Since $tainted does indeed flow to $untainted, Cqual++ returns error code 32, rather than 0.
Please note that we do not normally use Cqual++ manually in the way I am illustrating (we use it wrapped with other tools etc) so in preparing this Quick-Start a few bugs have been revealed to us.
You may ask yourself "wow, this is awfully slow just to analyze such a tiny program". The problem is that we are linking against Karl Chen's entire dataflow model for libc (note the flag -lc), which is really large. If you would like to avoid that delay you can write your own annotations just for the headers that you use and include only them. Doing this makes it much faster to run experiments: on a small program that doesn't load the libc dataflow model Cqual++ finishes immediately. The following examples are self-contained like this.
For lots more, see the main Cqual++ Documentation.
© 2002-2006 Daniel S. Wilkerson