public void GetLocation_Multiline_Invocation_StartAtZero_EndAtOne()
        {
            const string code = @"  // 1 - SQ line numbers
public class Class1                 // 2
{                                   // 3
    public string Foo(string s)     // 4
    {                               // 5
        var x =                     // 6 %0 = string.Trim(s)    --> SL = 7, SLO = 0, EL = 8, ELO = 1
s.Trim(                             // 7 x = __id(%0)           --> SL = 6, SLO = 12, EL = 8, ELO = 1
);                                  // 8
                                    // 9
                                    // 10
        return x;                   // 11
//23456789012345678901234567890     // SQ column offsets
    }
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            var block = ucfg.BasicBlocks[0];

            // Block locations are not used by the Security engine
            ucfg.BasicBlocks[0].Location.Should().BeNull();

            AssertLocation(ucfg.BasicBlocks[0].Instructions[0].Assigncall.Location,
                           startLine: 7, startLineOffset: 0, endLine: 8, endLineOffset: 1);
            AssertLocation(ucfg.BasicBlocks[0].Instructions[1].Assigncall.Location,
                           startLine: 6, startLineOffset: 12, endLine: 8, endLineOffset: 1);
        }
        public void SpecialBlocks_Goto()
        {
            const string code = @"
public class Class1
{
    public void Foo(int x)
    {
        switch (x)              // Branch(Jump0,Jump1,Exit)     |   Basic#0(Jump:#1,#2,#3)
        {
            case 0:             // Jump0(Jump1)                 |   Basic#1(Jump:#2)
                goto case 1;
            case 1:             // Jump1(Exit)                  |   Basic#2(Jump:#3)
                break;
        }
    }                           // Exit                         |   Basic#3(Ret)
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateJmpBlock(b, expectedId: "0", expectedJumps: new[] { "1", "2", "3" }),
                                        b => ValidateJmpBlock(b, expectedId: "2", expectedJumps: new[] { "3" }),
                                        b => ValidateJmpBlock(b, expectedId: "1", expectedJumps: new[] { "2" }),
                                        b => ValidateRetBlock(b, expectedId: "3", expectedReturnExpression: ConstValue)
                                        );
        }
        public void GetLocation_Returns_1Based_Line_0Based_LineOffset()
        {
            const string code = @"  // 1 - SQ line numbers
public class Class1                 // 2
{                                   // 3
    public string Foo(string s)     // 4
    {                               // 5
        var x = s.Trim();           // 6 %0 = string.Trim(s)    --> SL = 6, SLO = 16, EL = 6, ELO = 24
                                    // 7 x = __id(%0)           --> SL = 6, SLO = 12, EL = 6, ELO = 24
        return x;                   // 8
//23456789012345678901234567890     // SQ column offsets
    }
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            var block = ucfg.BasicBlocks[0];

            // Block locations are not used by the Security engine
            ucfg.BasicBlocks[0].Location.Should().BeNull();

            AssertLocation(ucfg.BasicBlocks[0].Instructions[0].Assigncall.Location,
                           startLine: 6, startLineOffset: 16, endLine: 6, endLineOffset: 24);
            AssertLocation(ucfg.BasicBlocks[0].Instructions[1].Assigncall.Location,
                           startLine: 6, startLineOffset: 12, endLine: 6, endLineOffset: 24);
        }
        public void Void_Method_Branch2()
        {
            const string code = @"
using System;
public class Class1
{
    public void Foo(string s)
    {
        if (true)                   // Branch (Next:Jump,Exit)  | Block#0(Jump:#1,#2)
            return;                 // Jump   (Next:Exit)       | Block#1(Ret)
        Console.WriteLine(s);       // Simple (Next:Exit)       | Block#2(Jump:#3)
                                    // Exit                     | Block#3(Ret)
    }
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            ucfg.Entries.Should().BeEquivalentTo(new[] { "0" });

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateJmpBlock(b, expectedId: "0", expectedJumps: new[] { "1", "2" }),
                                        b => ValidateRetBlock(b, expectedId: "1", expectedReturnExpression: ConstValue),
                                        b => ValidateJmpBlock(b, expectedId: "2", expectedJumps: "3"),
                                        b => ValidateRetBlock(b, expectedId: "3", expectedReturnExpression: ConstValue)
                                        );
        }
Beispiel #5
0
        public void ConstantExpressions_Share_The_Same_Instance()
        {
            const string code = @"
public class Class1
{
    private string field;
    public void Foo(string s)
    {
        string a = ""a"";
            // a := __id [ const ]
        string b = ""b"";
            // b := __id [ const ]
        string c = ""c"";
            // c := __id [ const ]
    }
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            var a = ucfg.BasicBlocks[0].Instructions[0].Assigncall.Args[0];
            var b = ucfg.BasicBlocks[0].Instructions[1].Assigncall.Args[0];
            var c = ucfg.BasicBlocks[0].Instructions[2].Assigncall.Args[0];

            // The constant expressions share the same instance of the Const value
            // for performance and simplicity. The protobuf serializer will deserialize
            // the values as a singleton again.
            a.Should().Be(b);
            a.Should().Be(c);
        }
        public void EntryPointMethod_Has_Additional_Block()
        {
            const string code = @"
using System.Web.Mvc;
public class Class1 : Controller
{
    public void Foo(string s)
    {                   //                  | Basic#1(Jump:#0) - contains entrypoint instruction and attributes
    }                   // Exit             | Basic#0(Ret)
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            ucfg.Entries.Should().BeEquivalentTo(new[] { "1" });
            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateRetBlock(b, expectedId: "0", expectedReturnExpression: ConstValue), // block from cfg
                                        b => ValidateJmpBlock(b, expectedId: "1", expectedJumps: new[] { "0" })          // fake entrypoint block
                                        );
        }
        public void SpecialBlocks_Lock()
        {
            const string code = @"
public class Class1
{
    public void Foo(object o, string s)
    {
        lock (o)        // Lock(Exit)       | Basic#0(Jump:#1)
        {
        }
    }                   // Exit             | Basic#1(Ret)
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateJmpBlock(b, expectedId: "0", expectedJumps: new[] { "1" }),
                                        b => ValidateRetBlock(b, expectedId: "1", expectedReturnExpression: ConstValue)
                                        );
        }
        public void String_Method_Simple()
        {
            const string code = @"
public class Class1
{
    public string Foo(string s)
    {
        return s;       // Jump   (Next:Exit)       | Block#0(Ret:s)
                        // Exit                     | Block#1(Ret:Const)// ignored when deserializing
    }
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            ucfg.Entries.Should().BeEquivalentTo(new[] { "0" });

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateRetBlock(b, expectedId: "0", expectedReturnExpression: "s"),
                                        b => ValidateRetBlock(b, expectedId: "1", expectedReturnExpression: ConstValue));
        }
        public void SpecialBlocks_Foreach()
        {
            const string code = @"
public class Class1
{
    public void Foo(string[] items)
    {
        foreach (var item in items)     // Foreach(BinaryBranch)            |   Basic#0
                                        // BinaryBranch(BinaryBranch,Exit)  |   Basic#1(Jump:#1,#2)
        {
        }
    }                                   // Exit                             |   Basic#2(Ret)
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateJmpBlock(b, expectedId: "0", expectedJumps: new[] { "1" }),
                                        b => ValidateJmpBlock(b, expectedId: "1", expectedJumps: new[] { "1", "2" }),
                                        b => ValidateRetBlock(b, expectedId: "2", expectedReturnExpression: ConstValue)
                                        );
        }
        public void SpecialBlocks_For()
        {
            const string code = @"
public class Class1
{
    public void Foo(string[] items)
    {
        for (int i = 0; i < items.Length; i++)      // For(BinaryBranch)                |   Basic#0(Jump:#1)
                                                    // BinaryBranch(Simple,Exit)        |   Basic#1(Jump:#2,#3)
        {                                           // Simple(BinaryBranch)             |   Basic#2(Jump:#1)
        }
    }                                               // Exit                             |   Basic#3(Ret)
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateJmpBlock(b, expectedId: "0", expectedJumps: new[] { "1", }),
                                        b => ValidateJmpBlock(b, expectedId: "1", expectedJumps: new[] { "2", "3" }),
                                        b => ValidateJmpBlock(b, expectedId: "2", expectedJumps: new[] { "1" }),
                                        b => ValidateRetBlock(b, expectedId: "3", expectedReturnExpression: ConstValue)
                                        );
        }
        public void SpecialBlocks_Using_Statement()
        {
            const string code = @"
public class Class1
{
    public void Foo(Func<IDisposable> factory)
    {
        using (var x = factory())   // Jump(Next:UsingEnd)      | Basic#0(Jump:#1)
        {
                                    // UsingEnd(Next:Exit)      | Basic#1(Jump:#2)
        }
                                    // Exit                     | Basic#2(Ret:Const)
    }
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateJmpBlock(b, expectedId: "0", expectedJumps: new[] { "1" }),
                                        b => ValidateJmpBlock(b, expectedId: "1", expectedJumps: new[] { "2" }),
                                        b => ValidateRetBlock(b, expectedId: "2", expectedReturnExpression: ConstValue)
                                        );
        }
        public void Serialize_Some_Method()
        {
            var code = @"
class C
{
    void Foo(string a, string b)
    {
        var x = a + b;
        if (true)
        {
            Bar(a, 1);
        }
        else
        {
            Bar(b, 2);
        }
    }
    void Bar(string a, int x) { }
}
";
            var dot  = UcfgSerializer.Serialize(UcfgVerifier.GetUcfgForMethod(code, "Foo"));

            dot.Should().BeIgnoringLineEndings(@"digraph ""C.Foo(string, string)"" {
ENTRY [shape=record label=""{ENTRY|a|b}""]
ENTRY -> 0
0 [shape=record label=""{BLOCK:0|\{ \""name\"": \""%0\"" \} __concat a,b|\{ \""name\"": \""x\"" \} __id %0|TERMINATOR JUMP: 1, 2}""]
0 -> 1
0 -> 2
1 [shape=record label=""{BLOCK:1|\{ \""name\"": \""%1\"" \} C.Bar(string, int) _this_,a,\""\""\""\""|TERMINATOR JUMP: 3}""]
1 -> 3
2 [shape=record label=""{BLOCK:2|\{ \""name\"": \""%2\"" \} C.Bar(string, int) _this_,b,\""\""\""\""|TERMINATOR JUMP: 3}""]
2 -> 3
3 [shape=record label=""{BLOCK:3|TERMINATOR RET: \""\""\""\""}""]
3 -> END
END [shape=record label=""{END}""]
}
");
        }
Beispiel #13
0
        public void Serialize_Some_Method()
        {
            var code = @"
class C
{
    void Foo(string a, string b)
    {
        var x = a + b;
        if (true)
        {
            Bar(a, 1);
        }
        else
        {
            Bar(b, 2);
        }
    }
    void Bar(string a, int x) { }
}
";
            var dot  = UcfgSerializer.Serialize(UcfgVerifier.GetUcfgForMethod(code, "Foo"));

            dot.Should().BeIgnoringLineEndings(@"digraph ""C.Foo(string, string)"" {
ENTRY [shape=record label=""{ENTRY|a|b}""]
ENTRY -> 0
0 [shape=record label=""{BLOCK:#0|%0 := __concat [ a, b ]|x := __id [ %0 ]|TERMINATOR: JUMP: #1, #2}""]
0 -> 1
0 -> 2
1 [shape=record label=""{BLOCK:#1|%1 := C.Bar(string, int) [ this, a, CONST ]|TERMINATOR: JUMP: #3}""]
1 -> 3
2 [shape=record label=""{BLOCK:#2|%2 := C.Bar(string, int) [ this, b, CONST ]|TERMINATOR: JUMP: #3}""]
2 -> 3
3 [shape=record label=""{BLOCK:#3|TERMINATOR: RET: CONST}""]
3 -> END
END [shape=record label=""{END}""]
}
");
        }
        public void Throw_Exception()
        {
            const string code = @"
public class Class1
{
    public string Foo(string s)
    {
        if (true)                       // Branch(Jump,Exit)    |   Basic#0(Jump:#1,#2)
        {
            throw new Exception();      // Jump(Exit)           |   Basic#1(Jump:#3)
        }
        return s;                       // Jump(Exit)           |   Basic#2(Ret:s)
    }                                   // Exit                 |   Basic#3(Ret:Const)
}";
            var          ucfg = UcfgVerifier.GetUcfgForMethod(code, "Foo");

            ucfg.Entries.Should().BeEquivalentTo(new[] { "0" });

            TestHelper.AssertCollection(ucfg.BasicBlocks,
                                        b => ValidateJmpBlock(b, expectedId: "0", expectedJumps: new[] { "1", "2" }),
                                        b => ValidateJmpBlock(b, expectedId: "1", expectedJumps: "3"),
                                        b => ValidateRetBlock(b, expectedId: "2", expectedReturnExpression: "s"),
                                        b => ValidateRetBlock(b, expectedId: "3", expectedReturnExpression: ConstValue));
        }