The first in a series of how Codesonar can be used to identify code quality issues such as Race Conditions covered by CWE 362 error messages. The article gives a code example of a race condition and explores how Codesonar presents the issue.

Welcome to the first in a series of posts looking at examples of different types of bugs that can easily find their way into your C/C++ codebase and how Codesonar, our static analysis tool, can detect and present the issues to you for review. I’ll be picking flaws as named by the Common Weakness Enumeration Specification (CWE), a scheme created to formalise the language used in naming general categories of software security vulnerabilities, each potentially subdivided into individual unique variations.

In this post, I will pick one of the most difficult to address, Race Conditions. What makes instances of this problem so hard to deal with is the difficulty of reproducing the bug consistently and the complexity of multiple concurrent paths of code execution that need to be considered by the person tasked with fixing the issue.

Briefly, what is a Race Condition? Consider this piece of code:

This is a contrived version of the classic credit/debit bank balance transaction code that contains a race condition. Compiling and running the above give us different outcomes depending on the order of interleaving of the statements in the CreditBalance and DebitBalance threads.

It’s possible for CreditBalance to partially complete and update balance to be £100 before the bonus is added, but the DebitBalance thread could become active and subtract £50 from the balance, upon which CreditBalance continues and now calculates the bonus on the balance as £50+ (£50 / 100) = £50.50. Other varied outcomes are possible! This happens because of thread scheduling decisions beyond our programs control. It may be noted as well that in the majority of cases where the above code is run on Linux, the behaviour is repeatable, resulting in the expected balance, highlighting one of the reasons why race conditions are so difficult to detect.

So what does Codesonar make of this code? Firstly, it is pretty straightforward to analyse. Codesonar works by observing native compilations of code, so in this rather simple case, we can look for problems with this command:

codesonar analyze RACECONDITION -preset concurrency gcc pthread.c -o pthread -lpthread

This will run Codesonar which will then run as a child process the build of the code, which could be anything, including makefiles, scripts, and so on, but in this case, is a direct call to gcc. As Codesonar detects the native build issue compilations, Codesonar reacts by invoking its own compiler to process the same source files, ready for eventual analysis. By default, Codesonar runs an out of the box set of checkers, looking for classic problems like null pointer dereferences, resource leaks, buffer overruns, uninitialised variables and many more. However, by default the analysis does not look for concurrency issues, hence the “-preset concurrency” arguments to enable the family of concurrency checkers.

Once complete, Codesonar reports several problems in this example:

Racecondition Warning List
Clicking on the first Data Race presents us with this view:

Data Race Details

As it is easily appreciated from the annotations on the pair of side by side thread contexts, Codesonar has identified that the global variable balance has been accessed for reading and writing in a potentially dangerous way, as there is no synchronisation protecting access to it by either thread. So, whilst this example may appear easy, I’m sure if you’ve written threaded code before, you’ve been caught out by the ease with which its easy to overlook adding suitable synchronisation and then suffered the consequences of unpredictable program behaviour, which has needed some dedicated puzzling overtime for the penny to drop what has happened – never mind the calamity of when these things get out to the customers.

With Codesonar, it took less than 30 seconds to have the precise and clear results ready (albeit a small piece of code in this case). Of course, if we were to have added synchronisation, Codesonar would have been sensitive to that and assuming it was done correctly (i.e, no deadlocks!), the code would have had a clean bill of health.

If you would like to try Codesonar on your source code please register for a free trial and we will get in touch.