Automatically find critical bugs and security vulnerabilities

Locate even the most elusive programming bugs and identify where code can be susceptible using Klocwork static analysis for C, C++, Java, and C# source code. Apply industry and security standards using pre-configured checkers, or create your own to support your organization's quality, SLA, and security mandates.

Klocwork finds hundreds of errors on well-validated, feasible execution paths by applying inter-procedural control flow, data flow, value-range propagation, and symbolic logic evaluation.

See the kinds of issues Klocwork finds, complete with selected bug examples, including code snippets and detailed descriptions.


C and C++ error examples

Many bugs created within C-derived languages are common to all derivations as well as to the root language. The most notable problems derive from C's requirement for the programmer to manage memory explicitly. This places an ongoing lifetime maintenance burden on the original developer as well as on every developer who inherits the code.

Whether it's newly created or legacy code, Klocwork finds a broad range of issues specific to C and C++ in these high-level categories:

NULL pointer dereferences

Dereferencing NULL pointers (or null object references in Java) causes numerous problems usually due to insufficient defenses being placed in code. It can happen anywhere, but we often see this type of error in larger systems where different developers are responsible for inter-dependent modules. Finding and addressing these errors earlier in the code development process creates a stronger build and more reliable code for years to come.

Check your own code for NULL dereferences now

Example: NULL pointer dereference

This is a simple example of NULL pointer dereference:

void foo(int* p) { *p = 32; }
void bar() { foo(NULL); }

When both of these functions are physically resident within the same module or the same subsystem, it is trivial to find the error. But, when these functions are separated into dependent subsystems written by different developers or different development teams, these errors become much more difficult to spot.

Value projection also adds another layer of complexity:

void foo(int* p) { *p = 32;
}
void bar(int x) {
int* p = NULL;
if( x == 15 || x == 20 )
p = &x;
if( x > 10 && x <= 20 )
foo(p);
}

In this example, certain values of the incoming parameter will cause errors and other values will not. Klocwork static code analysis understands how these values affect the available space of code paths - and alerts the developer immediately.

Buffer overflow

Buffer overflows, more generally referred to as array bounds violations, are errors that occur when code addresses elements of an array outside of the bounds that are defined for that data object. This coding pattern is at the heart of some of the most pernicious security vulnerabilities that exist in software today.

Check your own code for buffer overflow now

Example: Buffer overflow

Here's a simple example of a buffer overflow:

char arr[32];
for( int i = 0; i < 64; i++ )
arr[i] = (char)i;

In this example, the programmer is explicitly addressing memory outside of the range of the stack-based variable "arr." This will cause memory to be overwritten, potentially including the stack frame information that is required for the function to successfully return to its caller, etc.

While the specifics of the vulnerability change from instance to instance, the underlying problem is the same: performing array copy operations that are incorrectly or insufficiently guarded against exploit. Consider the following example:

void foo(unsigned char* data) {
unsigned char value[32];
int len = (int)data [0];
memcpy(value, data + 1, len);
}

The "memcpy" call will copy up to 256 bytes (the result of taking the zero'th element of the "data" buffer as its length) into a fixed sized stack-based array of only 32 bytes. If that data stream is available to the outside world, the system can be hacked.

For a high-profile example of this error in a long line of cases of buffer overflow causing stack corruption and vulnerability to code injection, consider Microsoft's well-published problems with animated cursor files.

Memory leak detection

One of the major problems with C-derived languages is the requirement for the programmer to manage memory completely. Buffers or structures that are allocated on the heap must be released appropriately when all references to those buffers or structures are about to head out of scope.

Check your own code for memory leaks now

Example: Memory leaks

This is a simple example of a memory leak:

void foo() { malloc(32); }

On return from this function, a data block of 32 bytes in length will languish unreferenced on the heap. If repeated enough times, the heap manager will fail.

By applying rigorous control and data flow analysis, Klocwork finds occurrences of memory leaks within code constructs that might easily pass manual inspection. For example:

typedef struct List {
struct List* next;
char* value;
int len;
} List;

void addToList(List* root, char* str) {
List* elem = (List*)malloc(sizeof(List));
if( elem ) {
elem->next = root->next;
root->next = elem;

/* Duplicate the string, allocating memory */
elem->value = strdup(str);
elem->len = strlen(str);
}
}

void removeList(List* root) {
List* ptr;
while( (ptr = root) != NULL ) {
root = root->next;

/* This releases the structure, but not the string */
free(ptr);
}
}

void foo() {
List* root = (List*)calloc(1, sizeof(List));
addToList(root, "hello");
addTolist(root, "world");
removeList(root);
free(root);
}

Here, a simple singly linked list leaks memory whenever it is cleaned up because while the list elements themselves are released, the strings to which each element points are not released. This type of error is particularly elusive in C++ with base and derived classes defining different elements that all must be cleaned up by the virtual destructor chain to guarantee no memory leaks.


C# error examples

C# developers face many of the same problems as users of other languages, plus many situations that are unique to the language and the underlying .Net framework. Klocwork detects a variety of situations in which code will cause failures, either immediately or over time, including:

Example: NULL object references

For example, the following invalid use of a NULL object reference:

Check your own code for NULL object references now

public class MyClass
{
    public static MyClass Create()
    {
        if (flag) return null;
        return new MyClass();
    }

    public static bool flag;

    public void foo()
    {
        //Do something
    }
}

public class MyOtherClass
{
    public void foo()
    {
        MyClass obj = MyClass.Create();
        obj.foo();
    }
}

In this case, there are a set of conditions under which the unchecked usage of the returned object 'obj' will cause a runtime failure, and result in a Klocwork report of a possible defect.

Resource is not disposed

Likewise, considering contractual obligations, the IDispose interface requires referencing objects use the sole interface member Dispose) before allowing an implementing object to go out of scope. For example, the following code will cause a defect to be reported:

Check your own code for resource is not disposed now

Example: Resource is not disposed

using System;
namespace Leaky
{
class ResourceLeak
{
class MyDisposable : IDisposable
{
public void Dispose() {
// Do something to remove associated resources
}
}
static void foo()
{
IDisposable d = new MyDisposable();
//Defect, function exits without closing the
resource
}
}
}

Modifying this code to either explicitly invoke the Dispose method on the object d, or by using the “using” construct, will remove the defect:

static void foo() { using( IDisposable d = new MyDisposable() ) { } // No defect, Dispose is automatically invoked }

Java error examples

As with every language, Java programming comes with its own unique set of common errors and vulnerabilities. Klocwork can detect a large number of issues in Java in the following categories:

Concurrency

Concurrent programming, or the practice of dividing up a program's execution context into two or more threads, is more common with multicore and multi-CPU hardware environments. Regardless of the programming language, there are several basic requirements that source code analysis must identify and address in a concurrent context.

Two of the most important concurrent programming requirements:

  • The ability to spot deadlock or livelock situations
  • The ability to spot race conditions

Deadlocks and livelocks refer to situations in which programs use locking semantics to guard sections of code against two or more threads of execution attempting access simultaneously. Typically, this involves modifying global data, but is by no means limited to that context. Without these capabilities, developers are left to guess for themselves how their programs will operate at runtime.

Check your own code for concurrency

Example: Concurrency

Consider the following example:

public void foo()
{
if( someCondition() ) {
synchronized( someGlobalSemaphore ) {
// First problem, this blocks all threads
Thread.Sleep(1000);
if( someOtherCondition() ) {
// Second problem, potential contention
synchronized( someOtherGlobalSemaphore ) {
...
}
}
}
}
}

Here, several different locking scenarios are shown, any of which can cause blocking situations, including:

  • Explicitly blocking one thread while holding a process-wide lock
  • Lock contention through potentially inconsistent acquisition semantics

Significant debug time can also be spent chasing almost impossible-to-replicate behavior caused by the race condition. This condition occurs when two or more threads each has an equal chance to modify data in each other’s' context. A simple example is static data in a re-entrant class, such as a servlet running within a J2EE container. Modifying class data on one thread that might be read or differently modified at the same time by another thread will lead to unexpected behavior.

Resource leaks

Like memory leaks, resource leaks can be crippling to an application and, over time, will lead to denial-of-service scenarios. The family of resource leaks to be most concerned with are those that tie into either operating system handles or descriptors, or to framework memory that requires explicit release semantics.

Klocwork supports a wide variety of resource semantics, from basic types like file descriptors and streams to framework-specific semantics for environments such as Google's Web Toolkit, Struts, Java Mail, J2ME, ImageIO, Hibernate, and many more.

A very common mistake is to assume that the runtime garbage collector (GC) will look after resources in the same way that it looks after memory references. However, while the memory associated with the object itself is collected by the GC, the resources associated with that object may not be cleaned up.

Check your own code for resource leaks now

Example: Resource leaks

Consider the following example:

public void foo(String name) throws IOException {
Reader r =
new InputStreamReader(new FileInputStream(name));
char ch;
while( (ch = r.read()) != -1 ) {
if( ch == ' ' )
return;
}
}

There are at least two types of resource that are collected under the input stream object in the example above:

  • Memory associated with the stream object itself, and with managing state within the stream
  • An operating system file descriptor or handle that relates to the underlying file within the file system

The GC will take care of the first aspect while leaving the underlying descriptor open, thus consuming valuable system resources over time and eventually resulting in a denial-of-service scenario.

Web application vulnerabilities

With many potential pitfalls inherent in creating web applications, this has quickly become one of the most popular areas to investigate automated approaches to debugging. Klocwork static code analysis detects vulnerabilities like:

  • SQL injection
  • Process or file injection
  • Code injection
  • Cross-site scripting (XSS)
  • Request forging

Each of these types of failure requires specific checks and analysis. However, many of the attack vectors exposed by such weaknesses can be generalized to the propagation of tainted data around an under-defensive design. That is, taking input from a user or another process and using that data without rigorous validation of its format, its range, or whatever else might make sense for the data type in question.

Check your own code for web vulnerabilities now

Web application vulnerabilities - An example

In a servlet context, for example, consider the following snippet:

public void doGet(HttpServletRequest req,
HttpServletResponse res)
{
String name = req.getParameter("username");
String pwd = req.getParameter("password");

// SQL Injection
int id = validateUser(username, password);

// XSS
String retstr = "User : " + name + " has ID: " + id;
res.getOutputStream().write(retstr.getBytes());
}

private int validateUser(String user, String pwd)
throws Exception
{
Statement stmt = myConnection.createStatement();
ResultSet rs;

rs = stmt.executeQuery("select id from users where
user='" + user + "' and key='" + pwd + "'");
return rs.next() ? rs.getInt(1) : -1;
}

This example exhibits several different kinds of common errors. Putting aside the obvious resource leakage and management issues, these include:

  • SQL injection via the use of an unfiltered incoming URL parameter as both username and password
  • Cross-site scripting, or request mirroring, by including the unfiltered incoming URL parameter in our response to the user

A malicious user could provide suitably marked-up URL parameters that would cause many problems. Likewise, applications that fail to validate strings that end up being used as file names are also open to file or process injection.

Klocwork detects all OWASP Top 10 vulnerabilities:

  • Injection
  • Broken Authentication and Session Management
  • Cross-Site Scripting (XSS)
  • Insecure Direct Object References
  • Security Misconfiguration
  • Sensitive Data Exposure
  • Missing Function Level Access Control
  • Cross-Site Request Forgery (CSRF)
  • Using Components with Know Vulnerabilities
  • Unvalidated Redirects and Forwards

Get a free trial of Klocwork static code analysis now