Merge pull request #8451 from michaelnebel/csharp/modelgenerator-improvements

C#: Model generator improvements and more tests
This commit is contained in:
Michael Nebel
2022-03-23 13:30:58 +01:00
committed by GitHub
6 changed files with 203 additions and 20 deletions

View File

@@ -1,6 +1,7 @@
/** Provides classes for collections. */
import csharp
import semmle.code.csharp.frameworks.system.Collections
private string modifyMethodName() {
result =
@@ -66,6 +67,12 @@ class CollectionType extends RefType {
}
}
/** Holds if `t` is a collection type. */
predicate isCollectionType(ValueOrRefType t) {
t.getABaseType*() instanceof SystemCollectionsIEnumerableInterface and
not t instanceof StringType
}
/** An object creation that creates an empty collection. */
class EmptyCollectionCreation extends ObjectCreation {
EmptyCollectionCreation() {

View File

@@ -1,6 +1,7 @@
import csharp
import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.commons.Util
private import semmle.code.csharp.commons.Collections
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
@@ -28,14 +29,8 @@ predicate asPartialModel = Csv::asPartialModel/1;
*/
predicate isRelevantType(Type t) { not t instanceof Enum }
private predicate isPrimitiveTypeUsedForBulkData(Type t) {
t.getName().regexpMatch("byte|char|Byte|Char")
}
private string parameterAccess(Parameter p) {
if
p.getType() instanceof ArrayType and
not isPrimitiveTypeUsedForBulkData(p.getType().(ArrayType).getElementType())
if isCollectionType(p.getType())
then result = "Argument[" + p.getPosition() + "].Element"
else result = "Argument[" + p.getPosition() + "]"
}

View File

@@ -1,6 +1,5 @@
| Summaries;BasicFlow;false;AssignFieldToArray;(System.Object[]);Argument[Qualifier];Argument[0].Element;taint |
| Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint |
| Summaries;BasicFlow;false;ReturnArrayElement;(System.Int32[]);Argument[0].Element;ReturnValue;taint |
| NoSummaries;PublicClassFlow;false;PublicReturn;(System.Int32);Argument[0];ReturnValue;taint |
| Summaries;BaseClassFlow;true;ReturnParam;(System.Int32);Argument[0];ReturnValue;taint |
| Summaries;BasicFlow;false;ReturnField;();Argument[Qualifier];ReturnValue;taint |
| Summaries;BasicFlow;false;ReturnParam0;(System.String,System.Object);Argument[0];ReturnValue;taint |
| Summaries;BasicFlow;false;ReturnParam1;(System.String,System.Object);Argument[1];ReturnValue;taint |
@@ -9,3 +8,23 @@
| Summaries;BasicFlow;false;ReturnSubstring;(System.String);Argument[0];ReturnValue;taint |
| Summaries;BasicFlow;false;ReturnThis;(System.Object);Argument[Qualifier];ReturnValue;value |
| Summaries;BasicFlow;false;SetField;(System.String);Argument[0];Argument[Qualifier];taint |
| Summaries;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);Argument[Qualifier];Argument[0].Element;taint |
| Summaries;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);Argument[1];Argument[0].Element;taint |
| Summaries;CollectionFlow;false;AssignFieldToArray;(System.Object[]);Argument[Qualifier];Argument[0].Element;taint |
| Summaries;CollectionFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint |
| Summaries;CollectionFlow;false;ReturnArrayElement;(System.Int32[]);Argument[0].Element;ReturnValue;taint |
| Summaries;CollectionFlow;false;ReturnFieldInAList;();Argument[Qualifier];ReturnValue;taint |
| Summaries;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);Argument[0].Element;ReturnValue;taint |
| Summaries;DerivedClass1Flow;false;ReturnParam1;(System.Int32,System.Int32);Argument[1];ReturnValue;taint |
| Summaries;DerivedClass2Flow;false;ReturnParam0;(System.Int32,System.Int32);Argument[0];ReturnValue;taint |
| Summaries;DerivedClass2Flow;false;ReturnParam;(System.Int32);Argument[0];ReturnValue;taint |
| Summaries;GenericFlow<>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);Argument[Qualifier];Argument[0].Element;taint |
| Summaries;GenericFlow<>;false;AddToGenericList<>;(System.Collections.Generic.List<S>,S);Argument[1];Argument[0].Element;taint |
| Summaries;GenericFlow<>;false;ReturnFieldInGenericList;();Argument[Qualifier];ReturnValue;taint |
| Summaries;GenericFlow<>;false;ReturnGenericElement<>;(System.Collections.Generic.List<S>);Argument[0].Element;ReturnValue;taint |
| Summaries;GenericFlow<>;false;ReturnGenericField;();Argument[Qualifier];ReturnValue;taint |
| Summaries;GenericFlow<>;false;ReturnGenericParam<>;(S);Argument[0];ReturnValue;taint |
| Summaries;GenericFlow<>;false;SetGenericField;(T);Argument[0];Argument[Qualifier];taint |
| Summaries;IEnumerableFlow;false;ReturnFieldInIEnumerable;();Argument[Qualifier];ReturnValue;taint |
| Summaries;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);Argument[0].Element;ReturnValue;taint |
| Summaries;IEnumerableFlow;false;ReturnIEnumerableElement;(System.Collections.Generic.IEnumerable<System.Object>);Argument[0].Element;ReturnValue;taint |

View File

@@ -0,0 +1,45 @@
using System;
namespace NoSummaries;
// Single class with a method that produces a flow summary.
// Just to prove that, if a method like this is correctly exposed, a flow summary will be captured.
public class PublicClassFlow
{
public int PublicReturn(int input)
{
return input;
}
}
public sealed class PublicClassNoFlow
{
private int PrivateReturn(int input)
{
return input;
}
internal int InternalReturn(int input)
{
return input;
}
private class PrivateClassNoFlow
{
public int ReturnParam(int input)
{
return input;
}
}
private class PrivateClassNestedPublicClassNoFlow
{
public class NestedPublicClassFlow
{
public int ReturnParam(int input)
{
return input;
}
}
}
}

View File

@@ -1,4 +1,6 @@
using System;
using System.Linq;
using System.Collections.Generic;
namespace Summaries;
@@ -31,6 +33,21 @@ public class BasicFlow
return s.Substring(0, 1);
}
public void SetField(string s)
{
tainted = s;
}
public string ReturnField()
{
return tainted;
}
}
public class CollectionFlow
{
private string tainted;
public int ReturnArrayElement(int[] input)
{
return input[0];
@@ -41,18 +58,117 @@ public class BasicFlow
target[0] = data;
}
public void SetField(string s)
{
tainted = s;
}
public string ReturnField()
{
return tainted;
}
public void AssignFieldToArray(object[] target)
{
target[0] = tainted;
}
public object ReturnListElement(List<object> input)
{
return input[0];
}
public void AddToList(List<object> input, object data)
{
input.Add(data);
}
public void AddFieldToList(List<string> input)
{
input.Add(tainted);
}
public List<string> ReturnFieldInAList()
{
return new List<string> { tainted };
}
}
public class IEnumerableFlow
{
private string tainted;
public IEnumerable<string> ReturnIEnumerable(IEnumerable<string> input)
{
return input;
}
public object ReturnIEnumerableElement(IEnumerable<object> input)
{
return input.First();
}
public IEnumerable<string> ReturnFieldInIEnumerable()
{
return new List<string> { tainted };
}
}
public class GenericFlow<T>
{
private T tainted;
public void SetGenericField(T t)
{
tainted = t;
}
public T ReturnGenericField()
{
return tainted;
}
public void AddFieldToGenericList(List<T> input)
{
input.Add(tainted);
}
public List<T> ReturnFieldInGenericList()
{
return new List<T> { tainted };
}
public S ReturnGenericParam<S>(S input)
{
return input;
}
public S ReturnGenericElement<S>(List<S> input)
{
return input[0];
}
public void AddToGenericList<S>(List<S> input, S data)
{
input.Add(data);
}
}
public abstract class BaseClassFlow
{
public virtual int ReturnParam(int input)
{
return input;
}
}
public class DerivedClass1Flow : BaseClassFlow
{
public int ReturnParam1(int input0, int input1)
{
return input1;
}
}
public class DerivedClass2Flow : BaseClassFlow
{
public override int ReturnParam(int input)
{
return input;
}
public int ReturnParam0(int input0, int input1)
{
return input0;
}
}

View File

@@ -0,0 +1 @@
semmle-extractor-options: /r:System.Linq.dll