Files
codeql/csharp/ql/test/query-tests/WriteOnlyContainer/WriteOnlyContainer.cs
2018-08-02 17:53:23 +01:00

313 lines
7.4 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
public class ContainerTest
{
// Test 1: Variable scopes
// Test 1a: Private field
private IList<int> c1a = new List<int> { 1, 2 }; // BAD: private
// Test 1b: protected field
protected IList<int> c1b = new List<int> { 1, 2 }; // GOOD: protected
// Test 1c: public field
public IList<int> c1c = new List<int> { 1, 2 }; // GOOD: public
// Test 1d: internal field
internal IList<int> c1d = new List<int> { 1, 2 }; // BAD: internal
void TestScopes()
{
c1a.Add(1);
c1b.Add(2);
c1c.Add(3);
c1d.Add(4);
// Test 1e: Local variable
IList<int> c1e = new List<int> { 1, 2 }; // BAD: local
c1e.Add(5);
}
// Test 2: Method names
void TestMethodNames()
{
// Test 2a: Writeonly method names
IList<int> c2a = new List<int> { 1, 2 }; // BAD: writeonly methods
c2a.Add(1);
c2a.Clear();
c2a.Insert(1, 2);
c2a.Remove(1);
c2a.RemoveAt(3);
// Test 2b: Read/write method names
IList<int> c2b = new List<int> { 1, 2 }; // GOOD: read method
bool b = c2b.Contains(1);
// Test 2c: Other method names
var c2c = new Stack(); // BAD
c2c.Push(1);
var c2d = new BitArray(10); // BAD
c2d.Set(1, true);
c2d.SetAll(false);
var c2j = new LinkedList<int>(); // BAD
c2j.AddFirst(1);
c2j.AddLast(2);
c2j.RemoveFirst();
c2j.RemoveLast();
}
// Test 3: Variable uses
IList<int> f() { return new List<int>(); }
void f(IList<int> x) { }
IList<int> g()
{
// Returned from function
var c3c = new List<int> { 2, 3, 4 }; // GOOD: returned
c3c.Add(5);
return c3c;
}
IList<int> h
{
get
{
// Returned from property
var c3d = new List<int>(); // GOOD: returned
c3d.Add(1);
return c3d;
}
}
IList<int> this[int i]
{
get
{
// Returned from property
var c3e = new List<int>(); // GOOD: returned
c3e.Add(1);
return c3e;
}
}
void TestAccessTypes()
{
// 3a: Unused
IList<int> c3a = new List<int> { 4, 5 }; // BAD
// 3b: Pass to function
IList<int> c3b = new List<int> { }; // GOOD: used
c3b.Add(1);
f(c3b);
// 3f: Access a property
var c3f = new List<int>(); // GOOD: accessed
c3f.Add(1);
int zero = c3f.Count;
}
// Test 4: Initialization type
private IList<int> c4a; // BAD: even though uninitialized
void TestInitializationTypes()
{
// Test 4a: Uninitialized
c4a.Add(1);
// Test 4b: Constructed from new
var c4b = new List<int>(); // BAD
c4b.Add(1);
// Test 4c: List initialized
var c4c = new List<int> { 2, 3, 4 }; // BAD
c4c.Add(1);
// Test 4d: Constructed from other expression
var c4d = f(); // GOOD
c4d.Add(1);
// Test 4e: In a foreach loop
List<List<string>> c4e = new List<List<string>> { new List<string> { "x" } };
foreach (var c4f in c4e) // GOOD: constructed from elsewehere
c4f.Remove("x");
int x = c4e.Count;
}
// Test 5: Assignment
void TestAssignment()
{
// Assigned from new container
IList<int> c5a; // BAD
c5a = new List<int>();
c5a.Add(1);
// Assigned from something else
IList<int> c5b; // GOOD: from f()
c5b = f();
c5b.Add(1);
// Assigned to something
IList<int> c5c = new List<int>(), c5d; // GOOD: assigned elsewhere
c5c.Add(1);
c5d = c5c;
// Assigned in an expression somewhere
IList<int> c5e = new List<int>(); // BAD: assigned in expr
for (int i = 0; i < 10; c5e = new List<int>(), ++i)
c5e.Add(1);
IList<int> c5f = new List<int>(); // GOOD: assigned in expr
for (int i = 0; i < 10; c5f = null, ++i)
c5f.Add(1);
}
class NonCollection
{
public void Add(int i) { }
}
// Test 6: Collection type
void TestCollections()
{
var c6a = new NonCollection(); // GOOD: not a collection
c6a.Add(1);
var c6b = new ArrayList(); // BAD
c6b.Add(1);
var c6c = new BitArray(32); // BAD
c6c.SetAll(true);
var c6d = new Hashtable(); // BAD
c6d.Add(1, 2);
var c6e = new Queue(); // BAD
c6e.Enqueue(1);
var c6f = new SortedList(); // BAD
c6f.Add(1, 2);
var c6g = new Stack(); // BAD
c6g.Push(1);
var c6h = new Dictionary<int, int>(); // BAD
c6h.Add(1, 2);
var c6i = new HashSet<int>(); // BAD
c6i.Add(1);
var c6j = new LinkedList<int>(); // BAD
c6j.AddFirst(1);
var c6k = new List<int>(); // BAD
c6k.Add(1);
var c6l = new Queue<int>(); // BAD
c6l.Enqueue(1);
var c6m = new SortedDictionary<int, int>(); // BAD
c6m.Add(1, 2);
var c6n = new SortedList<int, int>(); // BAD
c6n.Add(1, 2);
var c6o = new SortedDictionary<int, int>(); // BAD
c6o.Add(1, 2);
var c6p = new SortedSet<int>(); // BAD
c6p.Add(1);
var c6q = new Stack<int>(); // BAD
c6q.Push(1);
ICollection<int> c6u = new List<int>(); // BAD
c6u.Add(1);
IDictionary<int, int> c6v = new Dictionary<int, int>(); // BAD
c6v.Add(1, 2);
IEnumerable<int> c6w = new List<int>(); // GOOD
c6w.GetEnumerator();
IList<int> c6x = new List<int>(); // BAD
c6x.Add(12);
ISet<int> c6y = new HashSet<int>(); // BAD
c6y.Add(1);
}
void TestDynamicAccess()
{
// GOOD: dynamic
dynamic c7a = new List<int>();
c7a.Add(1);
// GOOD: cast to dynamic
var c7b = new List<int>();
c7b.Add(1);
dynamic x = (dynamic)c7b;
// GOOD: passed as param to InvokeMember
var c7c = new List<int>();
var t = typeof(List<int>);
t.InvokeMember("Add", System.Reflection.BindingFlags.InvokeMethod, null, c7c, new Object[] { 1 });
}
IList<int> c8a = new List<int>(); // BAD: no attribute
[Obsolete()]
IList<int> c8b = new List<int>(); // GOOD: has attribute
void TestAttributes()
{
c8a.Add(1);
c8b.Add(2);
}
public static void Main(string[] args)
{
ContainerTest t = new ContainerTest();
}
IEnumerable<IList<string>> TestIndirectInitializations(IList<string>[] stringss)
{
foreach (var strings in stringss)
strings.Add(""); // GOOD
if (stringss[0] is List<String> l)
l.Add(""); // GOOD
switch (stringss[0])
{
case List<String> l2:
l2.Add(""); // GOOD
break;
}
return stringss;
}
void Out(out List<string> strings)
{
strings = new List<string> { "a", "b", "c" };
}
void OutTest()
{
Out(out var strings); // BAD: but allow for now (only C# 7 allows discards)
}
}
// semmle-extractor-options: /r:System.Collections.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Expressions.dll /r:System.Collections.NonGeneric.dll