# 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.
- Configure and build Oink.
- Intercept the preprocessed files (.i files) from your own project.
- Run Cqual++.
- Read 'em and weep.

## 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.

- There is a long standing bug that the "same" error is often reported more than once. This is harder to fix that it may at first appear: the backend finds many "bad" dataflow paths and it could just report them all, but instead it uses heuristics to try to report the ones you are most likely to be interested in; in this example the heuristics are not managing to reduce all of them down to one.
- Per the previous point, in the output above, I have removed all but the last error report in order to eliminate redundancy. If you actually run this example and look at all of the output you will notice another bug: some of the error reports do not properly print the names of the variables or expressions in the path.
- We give source locations in the .i files instead of mapping them back to the .c files. We can map the locations back to the .c files, but doing that is, right now, strangely triggering another bug.

### 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.

- Jeff Foster's Canonical Cqual Example for the original and best example :-).
- For a more dramatic demo on C++, see the horrible target in the makefile oink/Demo.mk.

For lots more, see the main Cqual++ Documentation.

© 2002-2006 Daniel S. Wilkerson

##