Cqual++ Quick-Start

Oink Main Documentation

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.

Get Oink

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

Configure and Build Oink

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

Intercept your .i files

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

Run Cqual++

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.

Presentation bugs

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.

Going further

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