# NStatic and Exceptions

12/18/2005 10:07:03 PM

## NStatic and Exceptions

In my post, Static Analysis, George Tsiokos requests for feature…

Feature request: Exceptions!
I'm looking for a static analysis tool that can tell me all possible exceptions for an object's method call, constructor, etc. I would also like details on the code-path that generates the exception and not have specific ties to a specific framework version (so I could run an analysis of App X against .NET 1.1). From this post, it seems this should not be difficult for this tool to report.

The feature request is actually one of the main features of my static analysis tool. The .NET Framework makes it easy for analysis tools to detect errors by its ubiquitous use of exceptions and parameter validation. Scanning the Rotor sources or the framework’s IL is necessary for the tool.

For example, the following code is Microsoft’s implementation of String.ToCharArray:

public char[] ToCharArray(int startIndex, int length)
{
// Range check everything.
if (startIndex < 0 || startIndex > Length || startIndex > Length - length)
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
if (length < 0)
throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index"));

char[] chars = new char[length];
InternalCopyTo(startIndex, chars, 0, length);
return chars;
}

My tool would detect the two exceptions above and impose the if conditions as mandatory requirements on callers of this function. In addition, the exception’s message is captured and evaluated as an expression and outputted to the error log.

    array = s.ToCharArray(s.Length-count, count+1);

The tool would generate an error for the code above, because the expression is guaranteed to generate an exception.

In addition, any parameter that is dereferenced imposes a nonnull restriction, and any array parameter that is indexed imposes two requirement on the index—index >= 0 && length < param.Length.

The tool records all assumptions made before reaching an exception. If an assumption is redundant or contradictory, errors are also emitted.

if (X == Y + Z)
{
if (3*Y == 3*(X - Z))
....;
}
if (X*X - 6X < -9)
{
if (X == 4)
....;
}

In the first example, the second if statement is redundant, using essentially the same condition as the first, albeit in different form.

In the second example, X = 4 is not a solution to inequality presented by the first condition, therefore, the second condition always returns false and the body of that if statement will never be executed.