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.
It'd be nice if there was a configurable option for the tool to warn if an exception is not XML documented.
Posted by: Haacked | December 19, 2005 at 10:53 AM
Careful on that array indexing logic. It's a simple thing to alter the length of an array mid-method in such a way to invalidate a precondition.
Posted by: Keith J. Farmer | December 19, 2005 at 12:58 PM
Virtual methods are a killer.
I've written a similar tool, but have only been able to release it internal to MS. E.g. see http://www.bluebytesoftware.com/code/04/10/27/NetExceptions/default.html.
Posted by: Joe Duffy | December 19, 2005 at 06:30 PM
Keith, my tool makes a distinction between the array itself and the variable that points to the array.
The array itself can never change length, but the variable can point to another array.
Posted by: Wesner Moise | December 19, 2005 at 07:35 PM
Cool, I could definitely use a tool like this at work. Looking forward to playing with it.
Posted by: Judah | December 20, 2005 at 07:39 PM