C#: Fix bug in dataflow library.

This commit is contained in:
calum
2019-03-14 19:00:24 +00:00
parent d76a9805ae
commit d5a4dcebd6
15 changed files with 356 additions and 69 deletions

View File

@@ -44,7 +44,8 @@ private class ThrowingCall extends NonReturningCall {
exists(CIL::Method m, CIL::Type ex |
this.getTarget().matchesHandle(m) and
alwaysThrowsException(m, ex) and
c.getExceptionClass().matchesHandle(ex)
c.getExceptionClass().matchesHandle(ex) and
not m.isVirtual()
)
}

View File

@@ -646,7 +646,7 @@ module DataFlow {
sourceDecl.matchesHandle(result.(Callable))
or
// CIL callable without C# implementation in the database
not sourceDecl.matchesHandle(any(Callable k)) and
not sourceDecl.matchesHandle(any(Callable k | k.hasBody())) and
result = sourceDecl
else
// C# callable without C# implementation in the database
@@ -1188,7 +1188,7 @@ module DataFlow {
* nodes that may potentially be reached in flow from some source to some
* sink.
*/
private module Pruning {
module Pruning {
/**
* Holds if `node` is reachable from a source in the configuration `config`,
* ignoring call contexts.

View File

@@ -7,35 +7,53 @@ private import cil
private import semmle.code.csharp.dataflow.Nullness
private import semmle.code.cil.CallableReturns as CR
private predicate finalCallable(Callable c) {
not c.(Virtualizable).isVirtual() and
not exists(DeclarationWithGetSetAccessors p | c = p.getAnAccessor() and p.isVirtual())
}
/** Holds if callable `c` always returns null. */
predicate alwaysNullCallable(Callable c) {
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof AlwaysNullExpr)
finalCallable(c) and
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof AlwaysNullExpr)
)
}
/** Holds if callable `c` always returns a non-null value. */
predicate alwaysNotNullCallable(Callable c) {
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNotNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof NonNullExpr)
finalCallable(c) and
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNotNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof NonNullExpr)
)
}
/** Holds if callable 'c' always throws an exception. */
predicate alwaysThrowsCallable(Callable c) {
forex(ControlFlow::Node pre | pre = c.getExitPoint().getAPredecessor() |
pre.getElement() instanceof ThrowElement
finalCallable(c) and
(
forex(ControlFlow::Node pre | pre = c.getExitPoint().getAPredecessor() |
pre.getElement() instanceof ThrowElement
)
or
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysThrowsMethod(m))
)
or
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysThrowsMethod(m))
}
/** Holds if callable `c` always throws exception `ex`. */
predicate alwaysThrowsException(Callable c, Class ex) {
forex(ControlFlow::Node pre | pre = c.getExitPoint().getAPredecessor() |
pre.getElement().(ThrowElement).getThrownExceptionType() = ex
finalCallable(c) and
(
forex(ControlFlow::Node pre | pre = c.getExitPoint().getAPredecessor() |
pre.getElement().(ThrowElement).getThrownExceptionType() = ex
)
or
exists(CIL::Method m, CIL::Type t | m.matchesHandle(c) |
CR::alwaysThrowsException(m, t) and t.matchesHandle(ex)
)
)
or
exists(CIL::Method m, CIL::Type t | m.matchesHandle(c) | CR::alwaysThrowsException(m, t) and t.matchesHandle(ex))
}

View File

@@ -1,4 +1,11 @@
stubs
alwaysNull
| System.Object Dataflow.NullMethods.ReturnsNull2() | 0: ldarg.0, 1: call Dataflow.NullMethods.ReturnsNull, 2: ret |
| System.Object Dataflow.NullMethods.ReturnsNull() | 0: ldnull, 1: ret |
| System.Object Dataflow.NullMethods.ReturnsNullIndirect() | 0: ldarg.0, 1: call Dataflow.NullMethods.ReturnsNull, 2: ret |
| System.Object Dataflow.NullMethods.VirtualReturnsNull() | 0: ldnull, 1: ret |
| System.Object Dataflow.NullMethods.get_NullProperty() | 0: ldnull, 1: ret |
| System.Object Dataflow.NullMethods.get_VirtualNullProperty() | 0: ldnull, 1: ret |
| System.Object System.Collections.EmptyReadOnlyDictionaryInternal.get_Item(System.Object) | 0: ldarg.1, 1: brtrue.s 6:, 2: ldstr "key", 3: call System.SR.get_ArgumentNull_Key, 4: newobj System.ArgumentNullException..ctor, 5: throw, 6: ldnull, 7: ret |
alwaysNonNull
| System.ArgumentException System.ThrowHelper.GetAddingDuplicateWithKeyArgumentException(System.Object) |
@@ -11,6 +18,12 @@ alwaysNonNull
| System.ArgumentOutOfRangeException System.ThrowHelper.GetArgumentOutOfRangeException(System.ExceptionArgument,System.Int32,System.ExceptionResource) |
| System.Exception System.ThrowHelper.GetArraySegmentCtorValidationFailedException(System.Array,System.Int32,System.Int32) |
| System.InvalidOperationException System.ThrowHelper.GetInvalidOperationException(System.ExceptionResource) |
| System.Object Dataflow.NonNullMethods.ReturnsNonNull2() |
| System.Object Dataflow.NonNullMethods.ReturnsNonNull() |
| System.Object Dataflow.NonNullMethods.ReturnsNonNullIndirect() |
| System.Object Dataflow.NonNullMethods.get_VirtualNonNull() |
| System.Object Dataflow.NonNullMethods.get_VirtualNonNullProperty() |
| System.String Dataflow.NonNullMethods.get_NonNullProperty2() |
| System.Text.Encoder System.Text.ASCIIEncoding.GetEncoder() |
| System.Text.Encoder System.Text.Encoding.GetEncoder() |
| System.Text.Encoder System.Text.EncodingNLS.GetEncoder() |
@@ -20,6 +33,10 @@ alwaysNonNull
| System.Text.Encoder System.Text.UTF32Encoding.GetEncoder() |
| System.Text.Encoder System.Text.UnicodeEncoding.GetEncoder() |
alwaysThrows
| System.Object Dataflow.ThrowingMethods.AlwaysThrows() | System.InvalidOperationException | 0: newobj System.InvalidOperationException..ctor, 1: throw |
| System.Object Dataflow.ThrowingMethods.VirtualThrows() | System.Exception | 0: newobj System.Exception..ctor, 1: throw |
| System.Object Dataflow.ThrowingMethods.get_ThrowProperty() | System.Exception | 0: newobj System.Exception..ctor, 1: throw |
| System.Object Dataflow.ThrowingMethods.get_VirtualThrowProperty() | System.Exception | 0: newobj System.Exception..ctor, 1: throw |
| System.Object System.ValueTuple.get_Item(System.Int32) | System.IndexOutOfRangeException | 0: newobj System.IndexOutOfRangeException..ctor, 1: throw |
| System.Void System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(System.Object) | System.ArgumentException | 0: ldarg.0, 1: call System.ThrowHelper.GetAddingDuplicateWithKeyArgumentException, 2: throw |
| System.Void System.ThrowHelper.ThrowAggregateException(System.Collections.Generic.List<System.Exception>) | System.AggregateException | 0: ldarg.0, 1: newobj System.AggregateException..ctor, 2: throw |

View File

@@ -7,6 +7,13 @@ predicate relevantMethod(CIL::Method m) {
m.getName() = "get_Item"
or
m.getDeclaringType().getName() = "ThrowHelper"
or
m.getLocation().(CIL::Assembly).getName() = "DataFlow"
}
// Check that the assembly hasn't been marked as a stub.
query predicate stubs(string str) {
exists(CIL::Assembly asm | CIL::assemblyIsStub(asm) | str = asm.toString())
}
query predicate alwaysNull(string s, string d) {

View File

@@ -1,2 +1,2 @@
| dataflow.cs:41:9:41:18 | call to method DeadCode |
| dataflow.cs:49:9:49:18 | call to method DeadCode |
| dataflow.cs:57:9:57:18 | call to method DeadCode |
| dataflow.cs:65:9:65:18 | call to method DeadCode |

View File

@@ -0,0 +1,176 @@
using System;
namespace Dataflow
{
public class NullMethods
{
public object ReturnsNull() => null;
public object ReturnsNull2()
{
var x = ReturnsNull();
return x;
}
// Does not necessarily return null because of virtual method call.
public object NotReturnsNull() => VirtualReturnsNull();
public object ReturnsNullIndirect() => ReturnsNull();
public virtual object VirtualReturnsNull() => null;
public object NullProperty { get => null; }
public virtual object VirtualNullProperty { get => null; }
}
public class NonNullMethods
{
public object ReturnsNonNull() => new object();
public object ReturnsNonNull2()
{
var x = ReturnsNonNull();
return x;
}
public object ReturnsNonNullIndirect() => ReturnsNonNull();
public object NonNullProperty { get => 1; }
public string NonNullProperty2 { get => "not null"; }
public virtual object VirtualNonNull { get => "not null"; }
public bool cond = false;
public string MaybeNull()
{
if (cond)
return null;
else
return "not null";
}
public string MaybeNull2()
{
return cond ? null : "not null";
}
public virtual object VirtualNonNullProperty { get => "non null"; }
}
public class ThrowingMethods
{
public static object AlwaysThrows() => throw new InvalidOperationException();
public object AlwaysThrowsIndirect() => AlwaysThrows();
public virtual object VirtualThrows() => throw new Exception();
public object ThrowProperty { get => throw new Exception(); }
public virtual object VirtualThrowProperty { get => throw new Exception(); }
}
public class DataFlow
{
public object Taint1(object x) => x;
public object Taint2(object x) => Taint5(x);
public string Taint3(string s)
{
var x = s;
Console.WriteLine(s);
return x;
}
public object Taint5(object x) => Taint6(x);
private object Taint6(object x) => x;
}
public class TaintFlow
{
public string Taint1(string a, string b) => a + b;
public int Taint2(int a, int b) => a + b;
public int Taint3(int a) => -a;
public string TaintIndirect(string a, string b) => Taint1(a, b);
}
public class Properties
{
public int TrivialProperty1 { get; set; }
int field;
public int TrivialProperty2
{
get => field;
set { field = value; }
}
}
public class ThisAssemblyIsNotAStub
{
public void F()
{
// Ensure that the assembly isn't tagged as a stub
// Need to bump the average instruction count.
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
Console.WriteLine("This is not a stub assembly");
}
}
}

Binary file not shown.

View File

@@ -1,10 +1,17 @@
| dataflow.cs:16:18:16:26 | "tainted" | dataflow.cs:16:18:16:37 | call to method ToString |
| dataflow.cs:17:27:17:28 | 12 | dataflow.cs:17:18:17:29 | call to method Abs |
| dataflow.cs:18:27:18:27 | 2 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:18:30:18:30 | 3 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:20:45:20:53 | "tainted" | dataflow.cs:20:18:20:54 | call to method GetFullPath |
| dataflow.cs:27:44:27:46 | 1 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:27:49:27:51 | 2 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:64:30:64:33 | null | dataflow.cs:61:23:61:50 | ... ? ... : ... |
| dataflow.cs:64:30:64:33 | null | dataflow.cs:70:20:70:33 | call to method IndirectNull |
| dataflow.cs:71:23:71:26 | null | dataflow.cs:61:23:61:50 | ... ? ... : ... |
| dataflow.cs:18:18:18:26 | "tainted" | dataflow.cs:18:18:18:37 | call to method ToString |
| dataflow.cs:19:27:19:28 | 12 | dataflow.cs:19:18:19:29 | call to method Abs |
| dataflow.cs:20:27:20:27 | 2 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:20:30:20:30 | 3 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:22:45:22:53 | "tainted" | dataflow.cs:22:18:22:54 | call to method GetFullPath |
| dataflow.cs:29:44:29:46 | 1 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:29:49:29:51 | 2 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:40:34:40:37 | "d1" | dataflow.cs:40:18:40:38 | call to method Taint1 |
| dataflow.cs:41:34:41:37 | "d2" | dataflow.cs:41:18:41:38 | call to method Taint2 |
| dataflow.cs:42:34:42:37 | "d3" | dataflow.cs:42:18:42:38 | call to method Taint3 |
| dataflow.cs:46:28:46:32 | "t1a" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:46:35:46:39 | "t1b" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:49:35:49:38 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:49:41:49:44 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:101:20:101:33 | call to method IndirectNull |
| dataflow.cs:102:23:102:26 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |

View File

@@ -1,6 +1,7 @@
import csharp
import semmle.code.csharp.dataflow.DataFlow::DataFlow
// import DataFlow::PathGraph
class FlowConfig extends Configuration {
FlowConfig() { this = "FlowConfig" }

View File

@@ -1,15 +1,30 @@
alwaysNull
| dataflow.cs:54:21:54:35 | default(...) |
| dataflow.cs:56:27:56:56 | access to property DeclaringMethod |
| dataflow.cs:58:39:58:52 | call to method IndirectNull |
| dataflow.cs:70:21:70:35 | default(...) |
| dataflow.cs:74:39:74:52 | call to method IndirectNull |
| dataflow.cs:78:21:78:45 | call to method ReturnsNull |
| dataflow.cs:79:21:79:46 | call to method ReturnsNull2 |
| dataflow.cs:80:21:80:44 | access to property NullProperty |
alwaysNotNull
| dataflow.cs:55:23:55:34 | default(...) |
| dataflow.cs:56:27:56:30 | this access |
| dataflow.cs:56:27:56:40 | call to method GetType |
| dataflow.cs:57:30:57:33 | true |
| dataflow.cs:57:30:57:44 | call to method ToString |
| dataflow.cs:58:21:58:34 | this access |
| dataflow.cs:58:39:58:52 | this access |
| dataflow.cs:61:23:61:26 | this access |
| dataflow.cs:61:30:61:43 | this access |
| dataflow.cs:61:47:61:50 | this access |
| dataflow.cs:71:24:71:35 | default(...) |
| dataflow.cs:72:27:72:30 | this access |
| dataflow.cs:72:27:72:40 | call to method GetType |
| dataflow.cs:73:30:73:33 | true |
| dataflow.cs:73:30:73:44 | call to method ToString |
| dataflow.cs:74:21:74:34 | this access |
| dataflow.cs:74:39:74:52 | this access |
| dataflow.cs:77:27:77:52 | object creation of type NullMethods |
| dataflow.cs:78:21:78:31 | access to local variable nullMethods |
| dataflow.cs:79:21:79:31 | access to local variable nullMethods |
| dataflow.cs:80:21:80:31 | access to local variable nullMethods |
| dataflow.cs:83:23:83:51 | object creation of type NonNullMethods |
| dataflow.cs:84:24:84:30 | access to local variable nonNull |
| dataflow.cs:84:24:84:47 | call to method ReturnsNonNull |
| dataflow.cs:85:24:85:30 | access to local variable nonNull |
| dataflow.cs:85:24:85:55 | call to method ReturnsNonNullIndirect |
| dataflow.cs:86:24:86:30 | access to local variable nonNull |
| dataflow.cs:89:24:89:27 | this access |
| dataflow.cs:89:31:89:44 | this access |
| dataflow.cs:89:48:89:51 | this access |
| dataflow.cs:90:24:90:34 | access to local variable nullMethods |
| dataflow.cs:91:24:91:34 | access to local variable nullMethods |
| dataflow.cs:92:26:92:32 | access to local variable nonNull |

View File

@@ -1,18 +1,28 @@
| dataflow.cs:12:18:12:22 | "123" | dataflow.cs:12:18:12:37 | call to method CompareTo |
| dataflow.cs:12:34:12:36 | "b" | dataflow.cs:12:18:12:37 | call to method CompareTo |
| dataflow.cs:16:18:16:26 | "tainted" | dataflow.cs:16:18:16:37 | call to method ToString |
| dataflow.cs:17:27:17:28 | 12 | dataflow.cs:17:18:17:29 | call to method Abs |
| dataflow.cs:18:27:18:27 | 2 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:18:30:18:30 | 3 | dataflow.cs:18:18:18:31 | call to method Max |
| dataflow.cs:20:45:20:53 | "tainted" | dataflow.cs:20:18:20:54 | call to method GetFullPath |
| dataflow.cs:24:37:24:37 | 1 | dataflow.cs:24:18:24:56 | call to method DivRem |
| dataflow.cs:24:40:24:40 | 2 | dataflow.cs:24:18:24:56 | call to method DivRem |
| dataflow.cs:27:44:27:46 | 1 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:27:49:27:51 | 2 | dataflow.cs:27:18:27:52 | call to method IEEERemainder |
| dataflow.cs:30:60:30:60 | 1 | dataflow.cs:30:18:30:80 | call to method DivRem |
| dataflow.cs:30:63:30:63 | 2 | dataflow.cs:30:18:30:80 | call to method DivRem |
| dataflow.cs:64:30:64:33 | null | dataflow.cs:58:21:58:52 | ... ?? ... |
| dataflow.cs:64:30:64:33 | null | dataflow.cs:61:23:61:50 | ... ? ... : ... |
| dataflow.cs:64:30:64:33 | null | dataflow.cs:70:20:70:33 | call to method IndirectNull |
| dataflow.cs:71:23:71:26 | null | dataflow.cs:58:21:58:52 | ... ?? ... |
| dataflow.cs:71:23:71:26 | null | dataflow.cs:61:23:61:50 | ... ? ... : ... |
| dataflow.cs:11:18:11:22 | "123" | dataflow.cs:11:18:11:37 | call to method CompareTo |
| dataflow.cs:11:34:11:36 | "b" | dataflow.cs:11:18:11:37 | call to method CompareTo |
| dataflow.cs:18:18:18:26 | "tainted" | dataflow.cs:18:18:18:37 | call to method ToString |
| dataflow.cs:19:27:19:28 | 12 | dataflow.cs:19:18:19:29 | call to method Abs |
| dataflow.cs:20:27:20:27 | 2 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:20:30:20:30 | 3 | dataflow.cs:20:18:20:31 | call to method Max |
| dataflow.cs:22:45:22:53 | "tainted" | dataflow.cs:22:18:22:54 | call to method GetFullPath |
| dataflow.cs:26:37:26:37 | 1 | dataflow.cs:26:18:26:56 | call to method DivRem |
| dataflow.cs:26:40:26:40 | 2 | dataflow.cs:26:18:26:56 | call to method DivRem |
| dataflow.cs:29:44:29:46 | 1 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:29:49:29:51 | 2 | dataflow.cs:29:18:29:52 | call to method IEEERemainder |
| dataflow.cs:32:60:32:60 | 1 | dataflow.cs:32:18:32:80 | call to method DivRem |
| dataflow.cs:32:63:32:63 | 2 | dataflow.cs:32:18:32:80 | call to method DivRem |
| dataflow.cs:40:34:40:37 | "d1" | dataflow.cs:40:18:40:38 | call to method Taint1 |
| dataflow.cs:41:34:41:37 | "d2" | dataflow.cs:41:18:41:38 | call to method Taint2 |
| dataflow.cs:42:34:42:37 | "d3" | dataflow.cs:42:18:42:38 | call to method Taint3 |
| dataflow.cs:46:28:46:32 | "t1a" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:46:35:46:39 | "t1b" | dataflow.cs:46:18:46:40 | call to method Taint1 |
| dataflow.cs:47:28:47:28 | 2 | dataflow.cs:47:18:47:32 | call to method Taint2 |
| dataflow.cs:47:31:47:31 | 3 | dataflow.cs:47:18:47:32 | call to method Taint2 |
| dataflow.cs:48:28:48:28 | 1 | dataflow.cs:48:18:48:29 | call to method Taint3 |
| dataflow.cs:49:35:49:38 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:49:41:49:44 | "t6" | dataflow.cs:49:18:49:45 | call to method TaintIndirect |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:74:21:74:52 | ... ?? ... |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |
| dataflow.cs:95:30:95:33 | null | dataflow.cs:101:20:101:33 | call to method IndirectNull |
| dataflow.cs:102:23:102:26 | null | dataflow.cs:74:21:74:52 | ... ?? ... |
| dataflow.cs:102:23:102:26 | null | dataflow.cs:89:24:89:51 | ... ? ... : ... |

View File

@@ -1,3 +1,5 @@
| Dataflow.Properties.TrivialProperty1 |
| Dataflow.Properties.TrivialProperty2 |
| System.Collections.DictionaryEntry.Key |
| System.Collections.DictionaryEntry.Value |
| System.Reflection.AssemblyName.CodeBase |

View File

@@ -5,4 +5,6 @@ where
prop.getDeclaringType().hasQualifiedName("System.Reflection.AssemblyName")
or
prop.getDeclaringType().hasQualifiedName("System.Collections.DictionaryEntry")
or
prop.getDeclaringType().hasQualifiedName("Dataflow.Properties")
select prop.getQualifiedName()

View File

@@ -6,12 +6,14 @@ class Test
{
static void Main(string[] args)
{
// Indirect call to method
var c1 = "abc".Contains("a"); // Calls string.IndexOf()
var c2 = "123".CompareTo("b"); // Calls string.Compare()
var c3 = Tuple.Create("c", "d", "e"); // Calls Tuple constructor
}
void DataFlowThroughFramework()
{
// Dataflow through call
var f1 = "tainted".ToString();
var f2 = Math.Abs(12);
@@ -31,13 +33,27 @@ class Test
var m2 = "tainted".ToString().Contains("t");
}
void DeadCode() { }
void DataFlowThroughAssembly()
{
// Dataflow through test assembly
var dataflow = new Dataflow.DataFlow();
var d1 = dataflow.Taint1("d1");
var d2 = dataflow.Taint2("d2");
var d3 = dataflow.Taint3("d3");
System.Reflection.Assembly assembly;
// Taint tracking
var tt = new Dataflow.TaintFlow();
var t1 = tt.Taint1("t1a", "t1b");
var t2 = tt.Taint2(2, 3);
var t3 = tt.Taint3(1);
var t4 = tt.TaintIndirect("t6", "t6");
}
void DeadCode() { }
void CilAlwaysThrows()
{
assembly.GetModules(true); // Throws NotImplementedException
System.Reflection.Assembly.LoadFrom("", null, System.Configuration.Assemblies.AssemblyHashAlgorithm.SHA1); // Throws NotSupportedException
DeadCode();
}
@@ -52,13 +68,28 @@ class Test
void Nullness()
{
var @null = default(object);
var nonNull = default(int);
var nonNull1 = default(int);
var nullFromCil = this.GetType().DeclaringMethod;
var nonNullFromCil = true.ToString();
var null2 = NullFunction() ?? IndirectNull();
// Null from dataflow assembly
var nullMethods = new Dataflow.NullMethods();
var null3 = nullMethods.ReturnsNull(); // Null
var null4 = nullMethods.ReturnsNull2();
var null5 = nullMethods.NullProperty;
// NotNull
var nonNull = new Dataflow.NonNullMethods();
var nonNull2 = nonNull.ReturnsNonNull();
var nonNull3 = nonNull.ReturnsNonNullIndirect();
var nonNull4 = nonNull.NonNullProperty;
// The following are not always null:
var notNull = cond ? NullFunction() : this;
var notNull1 = cond ? NullFunction() : this;
var notNull2 = nullMethods.VirtualReturnsNull();
var notNull3 = nullMethods.VirtualNullProperty;
var notNonNull = nonNull.VirtualNonNull;
}
object IndirectNull() => null;