public void Annotation_NotEntryMethod_AttibutesAreIgnored() { const string code = @" namespace Namespace { public class FromBodyAttribute : System.Attribute { } public class NotAController { public object Foo([FromBody] long itemId, [FromBody] string itemId2) { var data = itemId; // data := __id [ const ] var data = itemId2; // data := __id [ itemId2 ] return null; } } }"; var ucfg = UcfgVerifier.VerifyInstructions(code, "Foo"); var entryPoints = UcfgVerifier.GetEntryPointInstructions(ucfg); entryPoints.Count.Should().Be(0); }
public void Assignments_Complex_Chaining() { const string code = @" namespace Namespace { public class Class1 { public Class1[] ArrayProperty { get; set; } public Class1[] arrayField; public string stringField; public void Foo(Class1 other, string s) { other.ArrayProperty[0].arrayField[1].stringField = s; // %0 := Namespace.Class1.ArrayProperty.get [ other ] // %1 := __arrayGet [ %0 ] // %2 := __id [ %1.arrayField ] // %3 := __arrayGet [ %2 ] // %3.stringField := __id [ s ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Assignments_Static_Property_On_Generic_Class() { const string code = @" namespace Namespace { public class Class1 { public void Foo() { var x = Bar<string>.Value; // %0 := Namespace.Bar<T>.Value.get [ Namespace.Bar<T> ] // x := __id [ %0 ] var y = Bar<int>.Value; // %1 := Namespace.Bar<T>.Value.get [ Namespace.Bar<T> ] // y := __id [ %1 ] } } public class Bar<T> { public static T Value { get { return default(T); } } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void ArrayCreation_New_ArrayInitializerInArrayInitializer() { const string code = @" namespace Namespace { public class Class1 { public void Foo(string data) { object[] a1 = new object[] { this, new string[] { data }, new Class1[] { this} }; // %0 := new object[] // %1 := new string[] // %2 := __arraySet [ %1 data ] // %3 := new Namespace.Class1[] // %4 := __arraySet [ %3 this ] // %5 := __arraySet [ %0 this ] // %6 := __arraySet [ %0 %1 ] // %7 := __arraySet [ %0 %3 ] // a1 := __id [ %0 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
[TestMethod] // Regression test for https://jira.sonarsource.com/browse/SONARSEC-199 public void Peach_Exception_UnexpectedTypeOfTargetForTheInstruction_Akka() { // Adpated from akka\src\core\Akka\IO\SocketEventArgsPool.cs const string code = @" namespace Akka.IO { using System; using System.Net.Sockets; internal class PreallocatedSocketEventAgrsPool { private EventHandler<SocketAsyncEventArgs> _onComplete = null; private SocketAsyncEventArgs CreateSocketAsyncEventArgs() { var e = new SocketAsyncEventArgs { UserToken = null }; // %0 := new System.Net.Sockets.SocketAsyncEventArgs // %1 := System.Net.Sockets.SocketAsyncEventArgs.SocketAsyncEventArgs() [ %0 ] // %2 := System.Net.Sockets.SocketAsyncEventArgs.UserToken.set [ %0 const ] // e := __id [ %0 ] e.Completed += _onComplete; // %3 := __id [ this._onComplete ] // %4 := System.Net.Sockets.SocketAsyncEventArgs.Completed.add [ System.Net.Sockets.SocketAsyncEventArgs const %3 ] return e; } } } "; UcfgVerifier.VerifyInstructions(code, "CreateSocketAsyncEventArgs"); }
public void Dynamic() { const string code = @" namespace Namespace { public class Class1 { public string Foo(Class1 c) { dynamic dyn = c.Bar; // dyn := __id [ const ] if (dyn.User != null) // %0 := dynamic.operator !=(dynamic, dynamic) [ __unknown const const ] { return ""bar""; } return c.ToString(); // %1 := object.ToString() [ c ] } } }"; 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 := new Namespace.Class1 // %3 := Namespace.Class1.Class1() [ %2 ] // %4 := __arraySet [ %1 data ] // %5 := __arraySet [ %1 %2 ] // 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 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Operator_SupportedTypes() { const string code = @" namespace Namespace { public class Class1 { public void Foo(string parameterString, Class1 some, Class1 other) { var result = parameterString == null; // %0 := string.operator ==(string, string) [ string parameterString const ] // result := __id [ %0 ] result = parameterString != null; // %1 := string.operator !=(string, string) [ string parameterString const ] // result := __id [ %1 ] Class1 classResult = some + other; // %2 := Namespace.Class1.operator +(Namespace.Class1, Namespace.Class1) [ Namespace.Class1 some other ] // classResult := __id [ %2 ] classResult = classResult + some + other; // %3 := Namespace.Class1.operator +(Namespace.Class1, Namespace.Class1) [ Namespace.Class1 classResult some ] // %4 := Namespace.Class1.operator +(Namespace.Class1, Namespace.Class1) [ Namespace.Class1 %3 other ] // classResult := __id [ %4 ] } public static Class1 operator+ (Class1 left, Class1 right) { return null; } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Indexer_GetAccess() { const string code = @" namespace Namespace { using System.Collections.Generic; public class Class1 { public void Foo(string s, List<string> list, Class1 myClass) { var character = s[0]; // %0 := string.this[int].get [ s const ] // character := __id [ %0 ] var i = list[0]; // %1 := System.Collections.Generic.List<T>.this[int].get [ list const ] // i := __id [ %1 ] var result = myClass[s, 0, 1.0]; // %2 := Namespace.Class1.this[string, int, double].get [ myClass s const const ] // result := __id [ %2 ] } public string this[string s, int i, double d] { get { return ""bar""; } } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void AssignmentOperator_UnsupportedTypes() { const string code = @" namespace Namespace { public class Class1 { public void Foo() { var i = 42 + 1; // i := __id [ const ] i += 1; // i := __id [ const ] i -= 1; // i := __id [ const ] i *= 1; // i := __id [ const ] i /= 1; // i := __id [ const ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Operator_UnsupportedTypes() { const string code = @" namespace Namespace { public class Class1 { public void Foo() { int x; double d; x = 1 + 2; // x := __id [ const ] x = 1 - 2; // x := __id [ const ] x = 1 * 2; // x := __id [ const ] x = 1 / 2; // x := __id [ const ] d = 1.0 / 2; // d := __id [ const ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Bug169_CreationError_RegressionTest_NullRef() { // SimplCommerce\src\Modules\SimplCommerce.Module.Reviews\Controllers\ReviewApiController.cs :: ChangeStatus // SimplCommerce\src\Modules\SimplCommerce.Module.ShoppingCart\Controllers\CartController.cs :: Remove // Exception at: CreateFromAttributSyntax->CreateAnnotationCall->CreateFunctionCall->ApplyAsTarget const string code = @" namespace Namespace { using System.Web.Mvc; public class FromBodyAttribute : System.Attribute { } public class CartController : Controller { [HttpPost] public object Remove([FromBody] long itemId) { // %0 := __entrypoint [ const ] return null; } } } "; UcfgVerifier.VerifyInstructions(code, "Remove"); }
public void PropertyChaining() { const string code = @" namespace Namespace { public class Class1 { public Class1 Property { get; set; } public static Class1 StaticProperty { get; set; } public void Foo() { Property.Property.Property = new Class1(); // %0 := Namespace.Class1.Property.get [ this ] // %1 := Namespace.Class1.Property.get [ %0 ] // %2 := new Namespace.Class1 // %3 := Namespace.Class1.Class1() [ %2 ] // %4 := Namespace.Class1.Property.set [ %1 %2 ] Class1.StaticProperty.Property = new Class1(); // %5 := Namespace.Class1.StaticProperty.get [ Namespace.Class1 ] // %6 := new Namespace.Class1 // %7 := Namespace.Class1.Class1() [ %6 ] // %8 := Namespace.Class1.Property.set [ %5 %6 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void FieldChaining() { const string code = @" namespace Namespace { public class Class1 { public Class1 field = new Class1(); public static Class1 staticField = new Class1(); public void Foo() { field.field.field = new Class1(); // %0 := __id [ this.field ] // %1 := __id [ %0.field ] // %2 := new Namespace.Class1 // %3 := Namespace.Class1.Class1() [ %2 ] // %1.field := __id [ %2 ] Class1.staticField.field = new Class1(); // %4 := __id [ Namespace.Class1.staticField ] // %5 := new Namespace.Class1 // %6 := Namespace.Class1.Class1() [ %5 ] // %4.field := __id [ %5 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Invocation_MethodNameArguments_Generate_Const() { const string code = @" namespace Ns1 { using System.Linq; public class Class1 { public void Foo(string[] args) { var result = args.Select(long.Parse); // %0 := System.Linq.Enumerable.Select<TSource, TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource, TResult>) [ System.Linq.Enumerable args const ] // result := __id [ %0 ] var result = args.Select(LocalParse); // %1 := System.Linq.Enumerable.Select<TSource, TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource, TResult>) [ System.Linq.Enumerable args const ] // result := __id [ %1 ] var result = args.Select(this.LocalParse); // %2 := System.Linq.Enumerable.Select<TSource, TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource, TResult>) [ System.Linq.Enumerable args const ] // result := __id [ %2 ] } private long LocalParse(string s) => 1l; } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Indexer_SetAccess() { const string code = @" namespace Namespace { using System.Collections.Generic; public class Class1 { public void Foo(string s, List<string> list, Class1 myClass) { list[0] = ""bar""; // %0 := System.Collections.Generic.List<T>.this[int].set [ list const ] myClass[s, 0, 1.0] = ""bar""; // %1 := Namespace.Class1.this[string, int, double].set [ myClass s const const ] } public string this[string s, int i, double d] { set {} } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Invocations_Explicit_Interfaces() { const string code = @" namespace Namespace { public class Class1 { public void Foobar(string s, IBar b1, Bar b2) { b1.Foo(s); // %0 := Namespace.IBar.Foo(string) [ b1 s ] b2.Foo(s); // %1 := Namespace.Bar.Foo(string) [ b2 s ] } } public class Bar : IBar { void IBar.Foo(string s) { } public void Foo(string s) { } } public interface IBar { void Foo(string s); } }"; UcfgVerifier.VerifyInstructions(code, "Foobar"); }
public void SafeCastWithConditionalFieldAccess() { const string code = @" namespace Namespace { using System; using System.Collections.Generic; using System.Linq; public class Class1 { private readonly List<object> _list; public override bool Equals(object obj) { return ListsEqual(_list, (obj as Class1)?._list); // %0 := __id [ this._list ] // %1 := __id [ obj ] // %2 := __id [ %1._list ] // %3 := Namespace.Class1.ListsEqual(System.Collections.Generic.List<object>, System.Collections.Generic.List<object>) [ this %0 %2 ] } private bool ListsEqual(List<object> x, List<object> y) => false } }"; UcfgVerifier.VerifyInstructions(code, "Equals"); }
public void ArrayCreation_New_Multi_NestedArrayInitializers() { const string code = @" namespace Namespace { // See MSDN: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/multidimensional-arrays using System.Collections.Generic; public class Class1 { public void Foo(int intdata1, int intdata2, string stringdata1, string stringdata2, Class1 objdata1, Class1 objdata2) { int[,] intMulti1 = new int[1, 2]; // %0 := new int[*,*] // intMulti1 := __id [ %0 ] // BUG: should handle the nested array initializers // SONARSEC-181: [C#] Handle multi-dimensional array initializers correctly int[,] intMulti2 = new int[,] { { 1, 2 }, { intdata1, intdata2 } }; // %1 := new int[*,*] // %2 := __arraySet [ %1 const ] // %3 := __arraySet [ %1 const ] // intMulti2 := __id [ %1 ] string[,] stringMulti1 = new string[1, 2]; // %4 := new string[*,*] // stringMulti1 := __id [ %4 ] string[,] stringMulti2 = new string[,] { { stringdata1, stringdata2 }, { null, "" } }; // %5 := new string[*,*] // %6 := __arraySet [ %5 const ] // %7 := __arraySet [ %5 const ] // stringMulti2 := __id [ %5 ] Class1[,] class1Multi1 = new Class1[1, 2]; // %8 := new Namespace.Class1[*,*] // class1Multi1 := __id [ %8 ] Class1[,] class1Multi2 = new Class1[,] { { objdata2, objdata1}, { null, new Class1() } }; // %9 := new Namespace.Class1[*,*] // %10 := __arraySet [ %9 const ] // %11 := __arraySet [ %9 const ] // %12 := new Namespace.Class1 // %13 := Namespace.Class1.Class1() [ %12 ] // class1Multi2 := __id [ %9 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Invocations_UsedNamedParameters() { const string code = @" namespace Namespace { public class Class1 { public void Foo(string s) { SendEmailAsync(s, false); // %0 := Namespace.Class1.SendEmailAsync(string, bool) [ this s const ] SendEmailAsync(body: s, isHtml: false); // %1 := Namespace.Class1.SendEmailAsync(string, bool) [ this s const ] SendEmailAsync(body: s); // %2 := Namespace.Class1.SendEmailAsync(string, bool) [ this s const ] SendEmailAsync(isHtml: false, body: s); // %3 := Namespace.Class1.SendEmailAsync(string, bool) [ this s const ] } public System.Threading.Tasks.Task SendEmailAsync(string body, bool isHtml = false) { return null; } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void ArrayCreation_New_ObjectArrayInitializer_PrimitivesAreNotIgnored() { const string code = @" namespace Namespace { public class Class1 { public void Foo(object data) { // Note: there is an optimisation in Java - arraySets are skipped for primitives. // We don't have this optimisation in C#. object[] a = new object[] { 1, data, null, 2.0, new string[]{} }; // %0 := new object[] // %1 := new string[] // %2 := __arraySet [ %0 const ] // %3 := __arraySet [ %0 data ] // %4 := __arraySet [ %0 const ] // %5 := __arraySet [ %0 const ] // %6 := __arraySet [ %0 %1 ] // a := __id [ %0 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Invocations_ExtensionMethods() { const string code = @" namespace Namespace { public class Class1 { private string field; public void Foo(string s) { string a; a = s.Ext(); // %0 := Namespace.Extensions.Ext(string) [ Namespace.Extensions s ] // a := __id [ %0 ] a = Extensions.Ext(s); // %1 := Namespace.Extensions.Ext(string) [ Namespace.Extensions s ] // a := __id [ %1 ] a = this.field.Ext(); // %2 := __id [ this.field ] // %3 := Namespace.Extensions.Ext(string) [ Namespace.Extensions %2 ] // a := __id [ %3 ] } } public static class Extensions { public static string Ext(this string s) { return s; } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void ArrayCreation_New_AsMethodParameter() { const string code = @" namespace Namespace { public class Class1 { public void Foo(string data) { // Initialization in method call Bar(new int[3]); // %0 := new int[] // %1 := Namespace.Class1.Bar(int[]) [ this %0 ] Bar(new string[2] { data }); // %2 := new string[] // %3 := __arraySet [ %2 data ] // %4 := Namespace.Class1.Bar(string[]) [ this %2 ] Bar(new Namespace.Class1[] { this }); // %5 := new Namespace.Class1[] // %6 := __arraySet [ %5 this ] // %7 := Namespace.Class1.Bar(Namespace.Class1[]) [ this %5 ] } public void Bar(int[] args) { } public void Bar(string[] args) { } public void Bar(Class1[] args) { } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Invocations_QualifiedNames_PropertyGets() { const string code = @" public static class GlobalClass { public static int Property { get; } = 42; } namespace Ns1 { using static GlobalClass; public static class OuterClass { public static int Property { get; } = 42; } namespace Inner { public static class InnerClass { public static int Property { get; } = 42; public static class NestedClass { public static int Property { get; } = 42; } } } public class Class1 { public void Foo() { int i; i = GlobalClass.Property; // %0 := GlobalClass.Property.get [ GlobalClass ] // i := __id [ %0 ] i = Ns1.OuterClass.Property; // %1 := Ns1.OuterClass.Property.get [ Ns1.OuterClass ] // i := __id [ %1 ] i = Ns1.Inner.InnerClass.Property; // %2 := Ns1.Inner.InnerClass.Property.get [ Ns1.Inner.InnerClass ] // i := __id [ %2 ] i = Ns1.Inner.InnerClass.NestedClass.Property; // %3 := Ns1.Inner.InnerClass.NestedClass.Property.get [ Ns1.Inner.InnerClass.NestedClass ] // i := __id [ %3 ] i = Property; // %4 := GlobalClass.Property.get [ GlobalClass ] // i := __id [ %4 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void TestSimpleFieldAccessAndAssignment() { const string code = @" namespace Namespace { public class BaseClass { public string baseField; } public class Class1 : BaseClass { public string field; public void Foo() { var variable = field; // %0 := __id [ this.field ] // variable := __id [ %0 ] variable = this.field; // %1 := __id [ this.field ] // variable := __id [ %1 ] variable = baseField; // %2 := __id [ this.baseField ] // variable := __id [ %2 ] variable = base.baseField; // %3 := __id [ this.baseField ] // variable := __id [ %3 ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void TestSimpleMethodInvocation() { const string code = @" namespace Namespace { public class Class1 { public string Bar1() { return null; } public void Bar2() { /* no-op */ } public void Foo() { var variable = Bar1(); // %0 := Namespace.Class1.Bar1() [ this ] // variable := __id [ %0 ] Bar1(); // %1 := Namespace.Class1.Bar1() [ this ] Bar2(); // %2 := Namespace.Class1.Bar2() [ this ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Assignments_Nested() { const string code = @" namespace Namespace { public class Class1 { public void Foo(string s) { string a, b, c; a = b = c = ""foo"" // c := __id [ const ] // b := __id [ c ] // a := __id [ b ] int x, y, z; x = y = z = 5; // z := __id [ const ] // y := __id [ z ] // x := __id [ y ] } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Invocations_LambdaArguments_Generate_Const() { const string code = @" using System; namespace Namespace { public class Class1 { public void Foo(string s) { var x = Bar(s, a => a); // %0 := Namespace.Class1.Bar(string, System.Func<string, string>) [ this s const ] // x := __id [ %0 ] this.Bar(s, a => a); // %1 := Namespace.Class1.Bar(string, System.Func<string, string>) [ this s const ] } public string Bar(string s, Func<string, string> a) { return s; } } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void AddAssignment_Parameter() { 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 ] parameterString += (((""foo""))); // %0 := __concat [ parameterString const ] // parameterString := __id [ %0 ] parameterString += localString; // %1 := __concat [ parameterString localString ] // parameterString := __id [ %1 ] parameterString += parameterString; // %2 := __concat [ parameterString parameterString ] // parameterString := __id [ %2 ] parameterString += fieldString; // %3 := __id [ this.fieldString ] // %4 := __concat [ parameterString %3 ] // parameterString := __id [ %4 ] parameterString += PropertyString; // %5 := Namespace.Class1.PropertyString.get [ this ] // %6 := __concat [ parameterString %5 ] // parameterString := __id [ %6 ] parameterString += parameterString += parameterString += ""123""; // %7 := __concat [ parameterString const ] // parameterString := __id [ %7 ] // %8 := __concat [ parameterString parameterString ] // parameterString := __id [ %8 ] // %9 := __concat [ parameterString parameterString ] // parameterString := __id [ %9 ] values[0] += Passthrough(parameterString += ""abc""); // %10 := __arrayGet [ values ] // %11 := __concat [ parameterString const ] // parameterString := __id [ %11 ] // %12 := Namespace.Class1.Passthrough(string) [ this parameterString ] // %13 := __concat [ %10 %12 ] // %14 := __arraySet [ values %13 ] } public string Passthrough(string s) => s; } }"; UcfgVerifier.VerifyInstructions(code, "Foo"); }
public void Annotation_EntryMethod_AttributeOnNonStringParameterIsHandled() { // Bug 169 const string code = @" namespace Namespace { using System.Web.Mvc; public class FromBodyAttribute : System.Attribute { } public class CartController : Controller { public object Remove([FromBody] long itemId) { var data = itemId; // data := __id [ const ] // %0 := __entrypoint [ const ] return null; } } }"; UcfgVerifier.VerifyInstructions(code, "Remove"); }