Saturday, June 12, 2004

I've been reading lately about PreFast, a tool for detecting fault in applications based on static analyis. Sadly, PreFact is for C++, so I wondered: can we do the same in C# ?

The test fault:

So I started with simple fault: a method that uses nullable argument and that does not check for nullity -> the NullReferenceException fault (NRE). Here are three method that illustrate the problem:

public class MyClass
{
    public void ArgumentNotChecked(Object arg)
    {
        string s=arg.ToString(); // if arg is null, NRE
    }

    public void ArgumentChecked(Object arg)
    {
        if (arg==null)
            throw new ArgumentNullException("arg");
        string s=arg.ToString(); // ok, we know arg is not null
    }

    public void ArgumentGuarded(Object arg)
    {
        if (arg!=null)
        { 
            string s=arg.ToString(); // ok, we know arg is not null
        }
    }
}

Sketch of the solution

The solution (I found) to this problem can be understood as taking all the possible path in the IL graph, while keeping track of the current state of the argument: Null, NonNull or Uncertain. When starting, the argument is uncertain, it could be null or not. If a method instance of the argument is called 3 things can happen:

  1. the argument is Null: we have found a bug,
  2. the argument is Uncertain: we have a possible bug. If by design, you always check parameters, this is a bug,
  3. the argument is NonNull: that's ok :)

In terms of graph theory (and QuickGraph), we need to apply the EdgeDepthFirstSearch algorithm using a visitior (IEdgeColorizerVisitor) that the job  described above. More that words, let's explain this on schemas.

Checking the ArgumentNotChecked method

This methods is very simply. In IL, it looks like this:

ldarg.1
call Object.ToString()

The corresponding graph is the following (ColorCode: Orange=Uncertain, Red=Null, Green=NonNull)

The EdgeDepthFirstSearch has only one step: it explorezs the ldarg.1 -> ToString() edge. Since the ldarg.1 status when calling ToString is Uncertain, it should output a warning. So in Reflector I get:

Gotcha!

Checking the ArgumentChecked method

This method is already a bit more complicated since there is a branch. The IL is:

L_0000: ldarg.1 
L_0001: brtrue.s L_000e
L_0003: ldstr "arg"
L_0008: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
L_000d: throw 
L_000e: ldarg.1 
L_000f: callvirt instance string object::ToString()
L_0014: stloc.0 
L_0015: ret

and the IL graph looks like this:

The EdgeDepthFirstSearchAlgorithm starts by examining the ldargs.1 -> brtrue.s edge.

If we find a brtrue.s, we can easily check if it is applied to ldarg1. If yes, then we should update the argument state in the child edges. The "then" branch will be tagged Null, the "else" branch will be tagged NonNull  as depicted in the figure below: 

Now, when we encounter the ToString() call on the argument, it's state is set to NonNull, so that's ok. 

Now, in Reflector, the fault analysis on the method should not find any warnings:

It worked!

Conclusion

Fault analysis can be seen as a natural application of graph theory and QuickGraph is a good for doing this. Although Reflector is a great tool, I think fault detection needs to be implemented as FxCop rules.... so stay tuned for new adventures.

posted on Saturday, June 12, 2004 7:25:00 AM UTC  #    Comments [5]
Tracked by:
"schwannoma" (online) [Trackback]
Monday, June 06, 2005 5:58:36 PM UTC
you're going to improve the code for millions of .NET developers out there with these great tools you're building.
nospamplease75@yahoo.com (Haacked)
Monday, June 06, 2005 5:58:37 PM UTC
Hi
<br>First of all, thanks for the good posts, keep'em comming!!! :)
<br>
<br>A question: What exactly do you do in Microsoft? If the aswer is building next generation developer tools then i'm ok with that, if not i'm wandering what is going to happen to ALL the great content you are writting, because if you are doing it just for fun, you are going to get tired someday (beleive me, I know what I'm talking about), or your job is going to absorb you to the point you will stop the great things you're doing (that happens ALL the time...).
<br>So, are you REALY planning to send this code to the FXCop guys, or do something about your wondeful <a title="MbUnit, Generating Unit Testing and Model Based Testing Framework for .NET Framework" href="http://mbunit.tigris.org" target="_blank">MbUnit</a> so it will be adopted inside Microsoft or something like that?
<br>
<br>Thanks again.
Juan Felipe Machado
Monday, June 06, 2005 5:58:37 PM UTC
:)
<br>
<br>Hi Juan,
<br>
<br>&gt;What exactly do you do in Microsoft ?
<br>
<br>I will be Software Design Enginer in Test. That's the official title. :) The mathematical description of testing is &quot;try to minimize the cost function a NP-hard problem in minimum time&quot;. So, that will be my objective.
<br>
<br>At the present moment, I'm finishing a PhD that I'm VERY bored about so that explains the noise of the blog... :)
<br>
<br>&gt;So, are you REALY planning to send this code to the FXCop guys, or do something about your wondeful <a title="MbUnit, Generating Unit Testing and Model Based Testing Framework for .NET Framework" href="http://mbunit.tigris.org" target="_blank">MbUnit</a> so it will be adopted inside Microsoft or something like that?
<br>
<br>I won't send this code to FxCops... but I'll make a FxCop.Graph addin for FxCop :)
Jonathan de Halleux
Monday, June 06, 2005 5:58:37 PM UTC
Peli's Blog
Monday, June 06, 2005 5:58:38 PM UTC
Richard Clark
Comments are closed.