public void Invocations_MethodCallOnFieldAccess()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        private string Field;

        public void Foo()
        {
            var x = Field.ToLower();
                // %0 := __id [ this.Field ]
                // %1 := string.ToLower() [ %0 ]
                // x := __id [ %1 ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void Invocation_ArgumentIsMethodResult()
        {
            const string code = @"
namespace Ns1
{
    public class Class1
    {
        public void Foo()
        {
            Add(GetData());
                // %0 := Ns1.Class1.GetData() [ this ]
                // %1 := Ns1.Class1.Add(int) [ this %0 ]
        }

        public int GetData() => 1;
        public void Add(int value) { }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
예제 #3
0
        public void Void_Method_Simple()
        {
            const string code = @"
using System;
public class Class1
{
    public void Foo(string s)
    {
        Console.WriteLine(s);       // Simple (Next:Exit)       | Block#0(Jump:#1)
                                    // Exit                     | Block#1(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" }),
                                        b => ValidateRetBlock(b, expectedId: "1", expectedReturnExpression: ConstValue)
                                        );
        }
예제 #4
0
        public void Ctor_Calling_Base()
        {
            var code = @"
class Foo : Bar
{
    // The ctor initializer instructions are executed before the ctor body

    public Foo() : base(""a"" + 5.ToString())       // %0 := __concat [ const const ]
                                                    // %1 := Bar.Bar(string) [ this %0 ]
    {
        var x = 5;                                  // x := __id [ const ]
    }
}
class Bar
{
    public Bar(string s) {}
}
";

            UcfgVerifier.VerifyInstructions(code, "Foo", isCtor: true);
        }
예제 #5
0
        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 Assignments_Array_Set_FieldPropertyMethodNew()
        {
            const string code = @"
using System.Collections.Generic;
namespace Namespace
{
    public class Class1
    {
        public void Foo()
        {
            var a = new object[1];
                // %0 := new object[]
                // a := __id [ %0 ]

            a[0] = Field;
                // %1 := __id [ this.Field ]
                // %2 := __arraySet [ a %1 ]

            a[0] = Property;
                // %3 := Namespace.Class1.Property.get [ this ]
                // %4 := __arraySet [ a %3 ]

            a[0] = GetData();
                // %5 := Namespace.Class1.GetData() [ this ]
                // %6 := __arraySet [ a %5 ]

            a[0] = new Class1();
                // %7 := new Namespace.Class1
                // %8 := Namespace.Class1.Class1() [ %7 ]
                // %9 := __arraySet [ a %7 ]
        }

        private string Field = null;
        private string Property { get; } = null;
        private object GetData() { return null; }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void ArrayCreation_New_AssignToProperty()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public void Foo(string data)
        {
            // Initialization in assignent
            IntProperty = new int[] { 0 };
                // %0 := new int[]
                // %1 := __arraySet [ %0 const ]
                // %2 := Namespace.Class1.IntProperty.set [ this %0 ]

            StringProperty = new string[] { data };
                // %3 := new string[]
                // %4 := __arraySet [ %3 data ]
                // %5 := Namespace.Class1.StringProperty.set [ this %3 ]

            Class1Property = new Class1[3];
                // %6 := new Namespace.Class1[]
                // %7 := Namespace.Class1.Class1Property.set [ this %6 ]

            Class1Property = new Class1[2] { null, this };
                // %8 := new Namespace.Class1[]
                // %9 := __arraySet [ %8 const ]
                // %10 := __arraySet [ %8 this ]
                // %11 := Namespace.Class1.Class1Property.set [ this %8 ]
        }

        private int[] IntProperty { get; set;} 
        public string[] StringProperty { get; set; }
        public Class1[] Class1Property { get; set; }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void Assignments_Simple()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public static string staticField;

        private string field;
        public void Foo(string s)
        {
            string a, b;

            a = s;
                // a := __id [ s ]

            a = ""boo"";
                // a := __id [ const ]

            int i;
            i = 5;
                // i := __id [ const ]

            field = s;
                // this.field := __id [ s ]
            this.field = s;
                // this.field := __id [ s ]

            staticField = s;
                // Namespace.Class1.staticField := __id [ s ]
            Class1.staticField = s;
                // Namespace.Class1.staticField := __id [ s ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
예제 #9
0
        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)
                                        );
        }
예제 #10
0
        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 Invocations_Explicit_Generic_Interfaces()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public void Foobar(string s, IBar b1, Bar b2, IBar<string> b3)
        {
            b1.Foo(s);
                // %0 := Namespace.IBar.Foo<T>(T) [ b1 s ]
            b2.Foo(s);
                // %1 := Namespace.Bar.Foo<T>(T) [ b2 s ]
            b2.Fooooo(s);
                // %2 := Namespace.Bar.Fooooo(string) [ b2 s ]
            b3.Fooooo(s);
                // %3 := Namespace.IBar<T>.Fooooo(T) [ b3 s ]
        }
    }
    public class Bar : IBar, IBar<string>
    {
        void IBar.Foo<T>(T s) { }
        public void Foo<T>(T s) { }
        public void Fooooo(string s) { }
        void IBar<string>.Fooooo(string s) { }
    }
    public interface IBar
    {
        void Foo<T>(T s);
    }
    public interface IBar<T>
    {
        void Fooooo(T s);
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foobar");
        }
예제 #12
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}""]
}
");
        }
예제 #13
0
        public void Annotation_EntryMethod_AttributeOnStringParameterIsHandled()
        {
            const string code = @"
namespace Namespace
{
    using System.Web.Mvc;

    public class FromBodyAttribute : System.Attribute { }

    public class CartController : Controller
    {
        public object Remove([FromBody] string itemId)
        {
            var data = itemId;
                // data := __id [ itemId ]
                // %0 := __entrypoint [ itemId ]
                // %1 := __annotate [ Namespace.FromBodyAttribute.FromBodyAttribute() itemId ]
                // itemId := __annotation [ %1 ]

            return null;
        }
    }
}";
            var          ucfg = UcfgVerifier.VerifyInstructions(code, "Remove");

            var entryPoints = UcfgVerifier.GetEntryPointInstructions(ucfg);

            entryPoints.Count.Should().Be(1);

            // Entry point location should be the "Remove" token.
            // Line numbers are 1-based, offsets are 0-based
            var actualLocation = entryPoints[0].Assigncall.Location;

            actualLocation.StartLine.Should().Be(10);
            actualLocation.EndLine.Should().Be(10);
            actualLocation.StartLineOffset.Should().Be(22);
            actualLocation.EndLineOffset.Should().Be(28);
        }
예제 #14
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|\{ \""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}""]
}
");
        }
예제 #15
0
        public void Void_Method_Branch1()
        {
            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)
                                    // Exit                     | Block#2(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 => ValidateRetBlock(b, expectedId: "2", expectedReturnExpression: ConstValue)
                                        );
        }
        public void Assignments_Array_Get()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public void Foo(string s, string[] a, string[][] jagged, string[,] multi)
        {
            s = a[0];
                // %0 := __arrayGet [ a ]
                // s := __id [ %0 ]

            s = ((a[0]));
                // %1 := __arrayGet [ a ]
                // s := __id [ %1 ]

            Bar(a[0]);
                // %2 := __arrayGet [ a ]
                // %3 := Namespace.Class1.Bar(string) [ this %2 ]

            s = jagged[0][0];
                // %4 := __arrayGet [ jagged ]
                // %5 := __arrayGet [ %4 ]
                // s := __id [ %5 ]

            s = multi[0, 0];
                // %6 := __arrayGet [ multi ]
                // s := __id [ %6 ]
        }

        public void Bar(string s) {}
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
예제 #17
0
        public void Pointers()
        {
            const string code = @"
using System;
namespace Namespace
{
    public class Class1
    {
        IntPtr ptrField;
        UIntPtr uPtrField;

        public void Foo(IntPtr ptrParam, UIntPtr uPtrParam)
        {
            int x = 100;
                // x := __id [ const ]

            int *ptr = &x;
                // ptr := __id [ const ]

            Console.WriteLine((int)ptr);
                // %0 := __id [ ptr ]
                // %1 := System.Console.WriteLine(int) [ System.Console %0 ]

            Console.WriteLine(*ptr);
                // %2 := System.Console.WriteLine(int) [ System.Console const ]

            ptrField = ptrParam;
                // this.ptrField := __id [ const ]
            uPtrField = uPtrParam;
                // this.uPtrField := __id [ const ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
예제 #18
0
        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));
        }
예제 #19
0
        public void Bug171_CreationError_RegressionTest_UnexpectedMergedNamespaceSymbol()
        {
            // SimplCommerce\src\Modules\SimplCommerce.Module.PaymentPaypalExpress\Controllers\PaypalExpressController.cs :: GetAccessToken
            // SimplCommerce\src\SimplCommerce.WebHost\Program.cs :: BuildWebHost2

            // At: UcfgExpressionService.Create

            // This code gives a similar repro, except with "SourceNamespaceSymbol" instead of
            // "MergedNamespaceSymbol" (
            const string code = @"

namespace Ns1
{
    namespace Inner
    {
        public class Builder
        {
            public static Builder CreateDefaultBuilder() => null;
        }
    }
}

namespace Ns2
{
    public class Class1
    {
        public void BuildWebHost2(string[] args)
        {
            Ns1.Inner.Builder.CreateDefaultBuilder();
                // %0 := Ns1.Inner.Builder.CreateDefaultBuilder() [ Ns1.Inner.Builder ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "BuildWebHost2");
        }
        public void Invocations_MethodsWithDefaultParameters()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public void Foo()
        {
            SendEmailAsync(""body"");
                // %0 := Namespace.Class1.SendEmailAsync(string, bool) [ this const const ]
            SendEmailAsync(""body"", isHtml: true);
                // %1 := Namespace.Class1.SendEmailAsync(string, bool) [ this const const ]
            SendEmailAsync(""body"", isHtml: false);
                // %2 := Namespace.Class1.SendEmailAsync(string, bool) [ this const const ]
        }

        public System.Threading.Tasks.Task SendEmailAsync(string body, bool isHtml = false)
        { return null; }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void Assignments_Array_Set()
        {
            const string code = @"
using System.Collections.Generic;
namespace Namespace
{
    public class Class1
    {
        public void Foo(string s, string[] a, string[][] jagged, string[,] multi)
        {
            a[0] = s;
                // %0 := __arraySet [ a s ]

            ((a[0])) = s;
                // %1 := __arraySet [ a s ]

            jagged[0][0] = s;
                // %2 := __arrayGet [ jagged ]
                // %3 := __arraySet [ %2 s ]

            multi[0, 0] = s;
                // %4 := __arraySet [ multi s ]

            ((jagged[0]))[0] = s;
                // %5 := __arrayGet [ jagged ]
                // %6 := __arraySet [ %5 s ]

            a[0] = a[1];
                // %7 := __arrayGet [ a ]
                // %8 := __arraySet [ a %7 ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void ArrayCreation_New_AssignToVariable_Object()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public void Foo(object data)
        {
            // All valid array syntaxes

            object[] a1 = new object[3];
                // %0 := new object[]
                // a1 := __id [ %0 ]

            object[] a2 = new object[2] { data, new Class1() };
                // %1 := new object[]
                // %2 := __arraySet [ %1 data ]
                // %3 := new Namespace.Class1
                // %4 := Namespace.Class1.Class1() [ %3 ]
                // %5 := __arraySet [ %1 %3 ]
                // a2 := __id [ %1 ]

            object[] a3 = new object[] { new object() };
                // %6 := new object[]
                // %7 := new object
                // %8 := object.Object() [ %7 ]
                // %9 := __arraySet [ %6 %7 ]
                // a3 := __id [ %6 ]
        }
    }
}";

            object[] a = { 1, "", null, 2.0, new string[] { } };
            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void ArrayCreation_New_AssignToVariable_String()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public void Foo(string data)
        {
            // All valid array syntaxes except x = { data };

            string[] a1 = new string[3];
                // %0 := new string[]
                // a1 := __id [ %0 ]

            string[] a2 = new string[] { null };
                // %1 := new string[]
                // %2 := __arraySet [ %1 const ]
                // a2 := __id [ %1 ]

            string[] a3 = new string[2] { ""x"", data };
                // %3 := new string[]
                // %4 := __arraySet [ %3 const ]
                // %5 := __arraySet [ %3 data ]
                // a3 := __id [ %3 ]

            string[] a4 = new[] { data };
                // %6 := new string[]
                // %7 := __arraySet [ %6 data ]
                // a4 := __id [ %6 ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
예제 #24
0
        public void ControllerMethod_Contains_EntryPoint_And_Attributes()
        {
            const string code = @"
using System.ComponentModel;
using System.Web.Mvc;
public class Class1 : Controller
{
    public class DummyAttribute : System.Attribute { }

    private string field;
    [HttpPost] // should be ignored
    public void Foo([Description]string s, [Missing]string x,
                    [Dummy] int i, [DummyAttribute]string s2) {}
        // %0 := __entrypoint [ s x const s2 ]
        // %1 := __annotate [ System.ComponentModel.DescriptionAttribute.DescriptionAttribute() s ]
        // s := __annotation [ %1 ]
        // i is a const so the attribute is ignored
        // the Missing attribute is unknown and is not included
        // %2 := __annotate [ Class1.DummyAttribute.DummyAttribute() s2 ]
        // s2 := __annotation [ %2 ]
}";
            var          ucfg = UcfgVerifier.VerifyInstructions(code, "Foo");

            var entryPoints = UcfgVerifier.GetEntryPointInstructions(ucfg);

            entryPoints.Count.Should().Be(1);

            // Entry point location should be the "Foo" token.
            // Line numbers are 1-based, offsets are 0-based
            var actualLocation = entryPoints[0].Assigncall.Location;

            actualLocation.StartLine.Should().Be(10);
            actualLocation.EndLine.Should().Be(10);
            actualLocation.StartLineOffset.Should().Be(16);
            actualLocation.EndLineOffset.Should().Be(19);
        }
        public void ArrayCreation_New_AssignToVariable_Int()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public void Foo(int data)
        {
            // All valid array syntaxes except x = { data };

            int[] a1 = new int[3];
                // %0 := new int[]
                // a1 := __id [ %0 ]

            int[] a2 = new int[] { 0 };
                // %1 := new int[]
                // %2 := __arraySet [ %1 const ]
                // a2 := __id [ %1 ]

            int[] a3 = new int[2] { 0, 1 };
                // %3 := new int[]
                // %4 := __arraySet [ %3 const ]
                // %5 := __arraySet [ %3 const ]
                // a3 := __id [ %3 ]

            int[] a4 = new[] { 42 };
                // %6 := new int[]
                // %7 := __arraySet [ %6 const ]
                // a4 := __id [ %6 ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
예제 #26
0
        public void AddAssignment_Property()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public string fieldString;
        public string PropertyString { get; set; }

        public void Foo(string parameterString, string[] values)
        {
            var localString = ""foo"";
                // localString := __id [ const ]

            PropertyString += (((""foo"")));
                // %0 := Namespace.Class1.PropertyString.get [ this ]
                // %1 := __concat [ %0 const ]
                // %2 := Namespace.Class1.PropertyString.set [ this %1 ]

            PropertyString += localString;
                // %3 := Namespace.Class1.PropertyString.get [ this ]
                // %4 := __concat [ %3 localString ]
                // %5 := Namespace.Class1.PropertyString.set [ this %4 ]

            PropertyString += parameterString;
                // %6 := Namespace.Class1.PropertyString.get [ this ]
                // %7 := __concat [ %6 parameterString ]
                // %8 := Namespace.Class1.PropertyString.set [ this %7 ]

            PropertyString += fieldString;
                // %9 := Namespace.Class1.PropertyString.get [ this ]
                // %10 := __id [ this.fieldString ]
                // %11 := __concat [ %9 %10 ]
                // %12 := Namespace.Class1.PropertyString.set [ this %11 ]

            PropertyString += PropertyString;
                // %13 := Namespace.Class1.PropertyString.get [ this ]
                // %14 := Namespace.Class1.PropertyString.get [ this ]
                // %15 := __concat [ %13 %14 ]
                // %16 := Namespace.Class1.PropertyString.set [ this %15 ]

            PropertyString += PropertyString += PropertyString += ""123"";
                // %17 := Namespace.Class1.PropertyString.get [ this ]
                // %18 := Namespace.Class1.PropertyString.get [ this ]
                // %19 := Namespace.Class1.PropertyString.get [ this ]
                // %20 := __concat [ %19 const ]
                // %21 := Namespace.Class1.PropertyString.set [ this %20 ]
                // %22 := __concat [ %18 %21 ]
                // %23 := Namespace.Class1.PropertyString.set [ this %22 ]
                // %24 := __concat [ %17 %23 ]
                // %25 := Namespace.Class1.PropertyString.set [ this %24 ]

            values[0] += Passthrough(PropertyString += ""abc"");
                // %26 := __arrayGet [ values ]
                // %27 := Namespace.Class1.PropertyString.get [ this ]
                // %28 := __concat [ %27 const ]
                // %29 := Namespace.Class1.PropertyString.set [ this %28 ]
                // %30 := Namespace.Class1.Passthrough(string) [ this %29 ]
                // %31 := __concat [ %26 %30 ]
                // %32 := __arraySet [ values %31 ]
        }

        public string Passthrough(string s) => s;
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
예제 #27
0
        public void AddAssignment_Field()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public string fieldString;
        public string PropertyString { get; set; }

        public void Foo(string parameterString, string[] values)
        {
            var localString = ""foo"";
                // localString := __id [ const ]

            fieldString += (((""foo"")));
                // %0 := __id [ this.fieldString ]
                // %1 := __concat [ %0 const ]
                // this.fieldString := __id [ %1 ]

            fieldString += localString;
                // %2 := __id [ this.fieldString ]
                // %3 := __concat [ %2 localString ]
                // this.fieldString := __id [ %3 ]

            fieldString += parameterString;
                // %4 := __id [ this.fieldString ]
                // %5 := __concat [ %4 parameterString ]
                // this.fieldString := __id [ %5 ]

            fieldString += fieldString;
                // %6 := __id [ this.fieldString ]
                // %7 := __id [ this.fieldString ]
                // %8 := __concat [ %6 %7 ]
                // this.fieldString := __id [ %8 ]

            fieldString += PropertyString;
                // %9 := __id [ this.fieldString ]
                // %10 := Namespace.Class1.PropertyString.get [ this ]
                // %11 := __concat [ %9 %10 ]
                // this.fieldString := __id [ %11 ]

            fieldString += fieldString += fieldString += ""123"";
                // %12 := __id [ this.fieldString ]
                // %13 := __id [ this.fieldString ]
                // %14 := __id [ this.fieldString ]
                // %15 := __concat [ %14 const ]
                // this.fieldString := __id [ %15 ]
                // %16 := __id [ this.fieldString ]
                // %17 := __concat [ %13 %16 ]
                // this.fieldString := __id [ %17 ]
                // %18 := __id [ this.fieldString ]
                // %19 := __concat [ %12 %18 ]
                // this.fieldString := __id [ %19 ]

            values[0] += Passthrough(fieldString += ""abc"");
                // %20 := __arrayGet [ values ]
                // %21 := __id [ this.fieldString ]
                // %22 := __concat [ %21 const ]
                // this.fieldString := __id [ %22 ]
                // %23 := Namespace.Class1.Passthrough(string) [ this this.fieldString ]
                // %24 := __concat [ %20 %23 ]
                // %25 := __arraySet [ values %24 ]
        }

        public string Passthrough(string s) => s;
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void Assignments_Ctors()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public static Class1 staticField;
        public Class1 field;

        public string Property { get; set; }
        public Class1() { }
        public Class1(string s) { }
        public Class1(Class1 other) { }
        public void Foo(string s)
        {
            Class1 c;
            c = new Class1(s);
                // %0 := new Namespace.Class1
                // %1 := Namespace.Class1.Class1(string) [ %0 s ]
                // c := __id [ %0 ]

            c = new Class1();
                // %2 := new Namespace.Class1
                // %3 := Namespace.Class1.Class1() [ %2 ]
                // c := __id [ %2 ]

            c = new Class1(new Class1(s));
                // %4 := new Namespace.Class1
                // %5 := Namespace.Class1.Class1(string) [ %4 s ]
                // %6 := new Namespace.Class1
                // %7 := Namespace.Class1.Class1(Namespace.Class1) [ %6 %4 ]
                // c := __id [ %6 ]

            c = new Class1(s)
                // %8 := new Namespace.Class1
                // %9 := Namespace.Class1.Class1(string) [ %8 s ]
            {
                Property = s,
                    // %10 := Namespace.Class1.Property.set [ %8 s ]
            };
                // c := __id [ %8 ]

            field = new Class1();
                // %11 := new Namespace.Class1
                // %12 := Namespace.Class1.Class1() [ %11 ]
                // this.field := __id [ %11 ]

            this.field = new Class1();
                // %13 := new Namespace.Class1
                // %14 := Namespace.Class1.Class1() [ %13 ]
                // this.field := __id [ %13 ]

            staticField = new Class1();
                // %15 := new Namespace.Class1
                // %16 := Namespace.Class1.Class1() [ %15 ]
                // Namespace.Class1.staticField := __id [ %15 ]

            Class1.staticField = new Class1();
                // %17 := new Namespace.Class1
                // %18 := Namespace.Class1.Class1() [ %17 ]
                // Namespace.Class1.staticField := __id [ %17 ]

            var other = new Class1();
                // %19 := new Namespace.Class1
                // %20 := Namespace.Class1.Class1() [ %19 ]
                // other := __id [ %19 ]

            other.field = this;
                // other.field := __id [ this ]
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void Assignments_Invocations()
        {
            const string code = @"
namespace Namespace
{
    public class BaseClass
    {
        public void BaseMethod() {}
    }

    public class Class1 : BaseClass
    {
        public string field;
        public void Foo(string s)
        {
            string a;
            a = s.ToLower();
                // %0 := string.ToLower() [ s ]
                // a := __id [ %0 ]

            a = (s + s).ToLower();
                // %1 := __concat [ s s ]
                // %2 := string.ToLower() [ %1 ]
                // a := __id [ %2 ]

            Bar(s.ToLower());
                // %3 := string.ToLower() [ s ]
                // %4 := Namespace.Class1.Bar(string) [ this %3 ]

            a = string.IsNullOrEmpty(s);
                // %5 := string.IsNullOrEmpty(string) [ string s ];
                // a := __id [ %5 ]

            a = A(B(C(s)));
                // %6 := Namespace.Class1.C(string) [ this s ]
                // %7 := Namespace.Class1.B(int) [ this %6 ]
                // %8 := Namespace.Class1.A(int) [ this %7 ]
                // a := __id [ %8 ]

            int x;
            x = O(s);
                // %9 := Namespace.Class1.O(object) [ this s ]
                // x := __id [ %9 ]

            this.Bar(s);
                // %10 := Namespace.Class1.Bar(string) [ this s ]

            base.BaseMethod();
                // %11 := Namespace.BaseClass.BaseMethod() [ this ]

            var other = new Class1();
                // %12 := new Namespace.Class1
                // %13 := Namespace.Class1.Class1() [ %12 ]
                // other := __id [ %12 ]

            other.Bar(s);
                // %14 := Namespace.Class1.Bar(string) [ other s ]

            Bar(field);
                // %15 := __id [ this.field ]
                // %16 := Namespace.Class1.Bar(string) [ this %15 ]

            Bar(other.field);
                // %17 := __id [ other.field ]
                // %18 := Namespace.Class1.Bar(string) [ this %17 ]

            StaticMethod(s);
                // %19 := Namespace.Class1.StaticMethod(string) [ Namespace.Class1 s ]

            Class1.StaticMethod(s);
                // %20 := Namespace.Class1.StaticMethod(string) [ Namespace.Class1 s ]

            a = field;
                // %21 := __id [ this.field ]
                // a := __id [ %21 ]
        }
        public void Bar(string s) { }
        public string A(int x) { return x.ToString(); }
        public int B(int x) { return x; }
        public int C(string s) { 5; }
        public int O(object o) { 5; }

        public static string StaticMethod(string s) { return s; }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }
        public void Assignments_Properties()
        {
            const string code = @"
namespace Namespace
{
    public class Class1
    {
        public static string StaticProperty { get; set; }

        public string Property { get; set; }
        public int IntProperty { get; set; }
        public object ObjectProperty { get; set; }
        public string Foo(string s)
        {
            string a;
            Property = s;
                // %0 := Namespace.Class1.Property.set [ this s ]

            a = Property;
                // %1 := Namespace.Class1.Property.get [ this ]
                // a := __id [ %1 ]

            Property = Property;
                // %2 := Namespace.Class1.Property.get [ this ]
                // %3 := Namespace.Class1.Property.set [ this %2 ]

            Foo(Property);
                // %4 := Namespace.Class1.Property.get [ this ]
                // %5 := Namespace.Class1.Foo(string) [ this %4 ]

            Property = Foo(Property);
                // %6 := Namespace.Class1.Property.get [ this ]
                // %7 := Namespace.Class1.Foo(string) [ this %6 ]
                // %8 := Namespace.Class1.Property.set [ this %7 ]

            ObjectProperty = s;
                // %9 := Namespace.Class1.ObjectProperty.set [ this s ]

            ObjectProperty = 5;
                // %10 := Namespace.Class1.ObjectProperty.set [ this const ]

            var x = IntProperty = 5;
                // %11 := Namespace.Class1.IntProperty.set [ this const ]
                // x := __id [ %11 ]

            this.Property = s;
                // %12 := Namespace.Class1.Property.set [ this s ]

            var other = new Class1();
                // %13 := new Namespace.Class1
                // %14 := Namespace.Class1.Class1() [ %13 ]
                // other := __id [ %13 ]

            other.Property = s;
                // %15 := Namespace.Class1.Property.set [ other s ]

            other.ObjectProperty = other.Property;
                // %16 := Namespace.Class1.Property.get [ other ]
                // %17 := Namespace.Class1.ObjectProperty.set [ other %16 ]

            Class1.StaticProperty = s;
                // %18 := Namespace.Class1.StaticProperty.set [ Namespace.Class1 s ]

            StaticProperty = s;
                // %19 := Namespace.Class1.StaticProperty.set [ Namespace.Class1 s ]

            a = StaticProperty;
                // %20 := Namespace.Class1.StaticProperty.get [ Namespace.Class1 ]
                // a := __id [ %20 ]

            a = Class1.StaticProperty;
                // %21 := Namespace.Class1.StaticProperty.get [ Namespace.Class1 ]
                // a := __id [ %21 ]

            return s;
        }
    }
}";

            UcfgVerifier.VerifyInstructions(code, "Foo");
        }