C#: Clean up implementation and remove CIL dataflow implementation.

This commit is contained in:
Michael Nebel
2024-02-27 15:28:08 +01:00
parent 1638183d18
commit 58a1353ddc
20 changed files with 68 additions and 380 deletions

View File

@@ -42,7 +42,9 @@ class Declaration extends DotNet::Declaration, Element, @cil_declaration {
}
}
private CS::Declaration toCSharpNonTypeParameter(Declaration d) { result.matchesHandle(d) }
private CS::Declaration toCSharpNonTypeParameter(Declaration d) {
result.(DotNet::Declaration).matchesHandle(d)
}
private CS::TypeParameter toCSharpTypeParameter(TypeParameter tp) {
toCSharpTypeParameterJoin(tp, result.getIndex(), result.getGeneric())

View File

@@ -3,7 +3,6 @@
private import semmle.code.csharp.commons.QualifiedName
import Element
import Type
private import dotnet
/**
* A type container. Either a namespace (`Namespace`) or a type (`Type`).

View File

@@ -5,8 +5,6 @@
import Member
import Stmt
import Type
private import cil
private import dotnet
private import semmle.code.csharp.ExprOrStmtParent
private import TypeRef
@@ -558,8 +556,6 @@ class TrivialProperty extends Property {
this.isAutoImplemented()
or
this.getGetter().trivialGetterField() = this.getSetter().trivialSetterField()
or
exists(CIL::TrivialProperty prop | this.matchesHandle(prop))
}
}

View File

@@ -7,7 +7,6 @@ import Assignable
import Callable
import Element
import Type
private import dotnet
private import semmle.code.csharp.ExprOrStmtParent
private import TypeRef

View File

@@ -3,56 +3,13 @@
*/
import csharp
private import cil
private import dotnet
private predicate isDisposeMethod(DotNet::Callable method) {
private predicate isDisposeMethod(Callable method) {
method.getName() = "Dispose" and
method.getNumberOfParameters() = 0
}
private predicate cilVariableReadFlowsToNode(CIL::Variable variable, DataFlow::Node n) {
n.asExpr() = variable.getARead()
or
exists(DataFlow::Node mid |
cilVariableReadFlowsToNode(variable, mid) and
DataFlow::localFlowStep(mid, n)
)
}
private predicate cilVariableReadFlowsTo(CIL::Variable variable, CIL::DataFlowNode n) {
cilVariableReadFlowsToNode(variable, DataFlow::exprNode(n))
}
private predicate disposedCilVariable(CIL::Variable variable) {
// `variable` is the `this` parameter on a dispose method.
isDisposeMethod(variable.(CIL::ThisParameter).getMethod())
or
// `variable` is passed to a method that disposes it.
exists(CIL::Call call, CIL::Parameter param |
cilVariableReadFlowsTo(variable, call.getArgumentForParameter(param)) and
disposedCilVariable(param)
)
or
// A parameter is disposed if its source declaration is disposed
disposedCilVariable(variable.(CIL::Parameter).getUnboundDeclaration())
or
// A variable is disposed if it's assigned to another variable
// that may be disposed.
exists(CIL::WriteAccess write |
cilVariableReadFlowsTo(variable, write.getExpr()) and
disposedCilVariable(write.getTarget())
)
}
private predicate disposedCSharpVariable(Variable variable) {
// A C# parameter is disposed if its corresponding CIL parameter is disposed
exists(CIL::Method m, CIL::Parameter p, int i |
disposedCilVariable(p) and p = m.getRawParameter(i)
|
variable = any(Callable c2 | c2.matchesHandle(m)).getRawParameter(i)
)
or
// Call to a method that disposes it
exists(Call call, int arg, VariableRead read |
read.getTarget() = variable and
@@ -83,7 +40,4 @@ private predicate disposedCSharpVariable(Variable variable) {
* Hold if `variable` might be disposed.
* This is a conservative overestimate.
*/
predicate mayBeDisposed(DotNet::Variable variable) {
disposedCSharpVariable(variable) or
disposedCilVariable(variable)
}
predicate mayBeDisposed(Variable variable) { disposedCSharpVariable(variable) }

View File

@@ -1,7 +1,6 @@
/** Provides predicates for working with fully qualified names. */
private import csharp
private import dotnet
/**
* Holds if namespace `n` has the qualified name `qualifier`.`name`.
@@ -9,8 +8,8 @@ private import dotnet
* For example if the qualified name is `System.Collections.Generic`, then
* `qualifier`=`System.Collections` and `name`=`Generic`.
*/
predicate namespaceHasQualifiedName(DotNet::Namespace n, string qualifier, string name) {
if n instanceof DotNet::GlobalNamespace
predicate namespaceHasQualifiedName(Namespace n, string qualifier, string name) {
if n instanceof GlobalNamespace
then qualifier = "" and name = ""
else (
exists(string pqualifier, string pname |

View File

@@ -4,7 +4,6 @@
import csharp
private import cil
private import dotnet
private import ControlFlow::SuccessorTypes
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.commons.ComparisonTest
@@ -844,8 +843,6 @@ class NullGuardedDataFlowNode extends GuardedDataFlowNode {
/** INTERNAL: Do not use. */
module Internal {
private import semmle.code.cil.CallableReturns
newtype TAbstractValue =
TBooleanValue(boolean b) { b = true or b = false } or
TIntegerValue(int i) { i = any(Expr e).getValue().toInt() } or
@@ -856,20 +853,11 @@ module Internal {
} or
TEmptyCollectionValue(boolean b) { b = true or b = false }
/** A callable that always returns a `null` value. */
private class NullCallable extends Callable {
NullCallable() {
exists(CIL::Method m | m.matchesHandle(this) | alwaysNullMethod(m) and not m.isVirtual())
}
}
/** Holds if expression `e` is a `null` value. */
predicate nullValue(Expr e) {
e instanceof NullLiteral
or
e instanceof DefaultValueExpr and e.getType().isRefType()
or
e.(Call).getTarget().getUnboundDeclaration() instanceof NullCallable
}
/** Holds if expression `e2` is a `null` value whenever `e1` is. */
@@ -890,11 +878,7 @@ module Internal {
/** A callable that always returns a non-`null` value. */
private class NonNullCallable extends Callable {
NonNullCallable() {
exists(CIL::Method m | m.matchesHandle(this) | alwaysNotNullMethod(m) and not m.isVirtual())
or
this = any(SystemObjectClass c).getGetTypeMethod()
}
NonNullCallable() { this = any(SystemObjectClass c).getGetTypeMethod() }
}
/** Holds if expression `e` is a non-`null` value. */

View File

@@ -6,8 +6,6 @@
*/
import csharp
private import cil
private import semmle.code.cil.CallableReturns
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.frameworks.System
@@ -39,15 +37,6 @@ private class ThrowingCall extends NonReturningCall {
or
this.(FailingAssertion).getAssertionFailure().isException(c.getExceptionClass())
or
exists(Callable target, CIL::Method m, CIL::Type ex |
target = this.getTarget() and
not target.hasBody() and
target.matchesHandle(m) and
alwaysThrowsException(m, ex) and
c.getExceptionClass().matchesHandle(ex) and
not m.isVirtual()
)
or
this =
any(MethodCall mc |
mc.getTarget()

View File

@@ -3,9 +3,7 @@
*/
import csharp
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
@@ -15,19 +13,11 @@ private predicate finalCallable(Callable c) {
/** Holds if callable `c` always returns null. */
predicate alwaysNullCallable(Callable c) {
finalCallable(c) and
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof AlwaysNullExpr)
)
forex(Expr e | c.canReturn(e) | e instanceof AlwaysNullExpr)
}
/** Holds if callable `c` always returns a non-null value. */
predicate alwaysNotNullCallable(Callable c) {
finalCallable(c) and
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNotNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof NonNullExpr)
)
forex(Expr e | c.canReturn(e) | e instanceof NonNullExpr)
}

View File

@@ -1,6 +1,4 @@
private import csharp
private import cil
private import dotnet
private import DataFlowImplCommon as DataFlowImplCommon
private import DataFlowPublic
private import DataFlowPrivate
@@ -14,29 +12,12 @@ private import semmle.code.csharp.frameworks.system.collections.Generic
/**
* Gets a source declaration of callable `c` that has a body or has
* a flow summary.
*
* If the callable has both CIL and source code, return only the source
* code version.
*/
DotNet::Callable getCallableForDataFlow(DotNet::Callable c) {
exists(DotNet::Callable unboundDecl | unboundDecl = c.getUnboundDeclaration() |
result.hasBody() and
if unboundDecl.getFile().fromSource()
then
// C# callable with C# implementation in the database
result = unboundDecl
else
if unboundDecl instanceof CIL::Callable
then
// CIL callable with C# implementation in the database
unboundDecl.matchesHandle(result.(Callable))
or
// CIL callable without C# implementation in the database
not unboundDecl.matchesHandle(any(Callable k | k.hasBody())) and
result = unboundDecl
else
// C# callable without C# implementation in the database
unboundDecl.matchesHandle(result.(CIL::Callable))
Callable getCallableForDataFlow(Callable c) {
exists(Callable unboundDecl | unboundDecl = c.getUnboundDeclaration() |
unboundDecl.hasBody() and
unboundDecl.getFile().fromSource() and
result = unboundDecl
)
}
@@ -67,7 +48,7 @@ private module Cached {
*/
cached
newtype TDataFlowCallable =
TDotNetCallable(DotNet::Callable c) { c.isUnboundDeclaration() } or
TCallable(Callable c) { c.isUnboundDeclaration() } or
TSummarizedCallable(DataFlowSummarizedCallable sc) or
TFieldOrPropertyCallable(FieldOrProperty f) or
TCapturedVariableCallable(LocalScopeVariable v) { v.isCaptured() }
@@ -81,10 +62,6 @@ private module Cached {
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
cfn.getAstNode() = dc
} or
TCilCall(CIL::Call call) {
// No need to include calls that are compiled from source
not call.getImplementation().getMethod().compiledFromSource()
} or
TSummaryCall(FlowSummary::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -197,7 +174,7 @@ class RefReturnKind extends OutRefReturnKind, TRefReturnKind {
/** A callable used for data flow. */
class DataFlowCallable extends TDataFlowCallable {
/** Gets the underlying source code callable, if any. */
DotNet::Callable asCallable() { this = TDotNetCallable(result) }
Callable asCallable() { this = TCallable(result) }
/** Gets the underlying summarized callable, if any. */
FlowSummary::SummarizedCallable asSummarizedCallable() { this = TSummarizedCallable(result) }
@@ -208,7 +185,7 @@ class DataFlowCallable extends TDataFlowCallable {
LocalScopeVariable asCapturedVariable() { this = TCapturedVariableCallable(result) }
/** Gets the underlying callable. */
DotNet::Callable getUnderlyingCallable() {
Callable getUnderlyingCallable() {
result = this.asCallable() or result = this.asSummarizedCallable()
}
@@ -235,8 +212,7 @@ class DataFlowCallable extends TDataFlowCallable {
abstract class DataFlowCall extends TDataFlowCall {
/**
* Gets a run-time target of this call. A target is always a source
* declaration, and if the callable has both CIL and source code, only
* the source code version is returned.
* declaration.
*/
abstract DataFlowCallable getARuntimeTarget();
@@ -250,7 +226,7 @@ abstract class DataFlowCall extends TDataFlowCall {
abstract DataFlowCallable getEnclosingCallable();
/** Gets the underlying expression, if any. */
final DotNet::Expr getExpr() { result = this.getNode().asExpr() }
final Expr getExpr() { result = this.getNode().asExpr() }
/** Gets the argument at position `pos` of this call. */
final ArgumentNode getArgument(ArgumentPosition pos) { result.argumentOf(this, pos) }
@@ -348,33 +324,6 @@ class ExplicitDelegateLikeDataFlowCall extends DelegateDataFlowCall, TExplicitDe
override Location getLocation() { result = cfn.getLocation() }
}
/** A CIL call relevant for data flow. */
class CilDataFlowCall extends DataFlowCall, TCilCall {
private CIL::Call call;
CilDataFlowCall() { this = TCilCall(call) }
/** Gets the underlying CIL call. */
CIL::Call getCilCall() { result = call }
override DataFlowCallable getARuntimeTarget() {
// There is no dispatch library for CIL, so do not consider overrides for now
result.getUnderlyingCallable() = getCallableForDataFlow(call.getTarget())
}
override ControlFlow::Nodes::ElementNode getControlFlowNode() { none() }
override DataFlow::ExprNode getNode() { result.getExpr() = call }
override DataFlowCallable getEnclosingCallable() {
result.asCallable() = call.getEnclosingCallable()
}
override string toString() { result = call.toString() }
override Location getLocation() { result = call.getLocation() }
}
/**
* A synthesized call inside a callable with a flow summary.
*

View File

@@ -1,6 +1,4 @@
private import csharp
private import cil
private import dotnet
private import DataFlowPublic
private import DataFlowDispatch
private import DataFlowImplCommon
@@ -18,8 +16,6 @@ private import semmle.code.csharp.frameworks.NHibernate
private import semmle.code.csharp.frameworks.Razor
private import semmle.code.csharp.frameworks.system.Collections
private import semmle.code.csharp.frameworks.system.threading.Tasks
private import semmle.code.cil.Ssa::Ssa as CilSsa
private import semmle.code.cil.internal.SsaImpl as CilSsaImpl
private import codeql.util.Unit
private import codeql.util.Boolean
@@ -57,15 +53,15 @@ abstract class NodeImpl extends Node {
/** Do not call: use `getType()` instead. */
cached
abstract DotNet::Type getTypeImpl();
abstract Type getTypeImpl();
/** Gets the type of this node used for type pruning. */
DataFlowType getDataFlowType() {
forceCachingInSameStage() and
exists(Type t0 | result.asGvnType() = Gvn::getGlobalValueNumber(t0) |
t0 = getCSharpType(this.getType())
t0 = this.getType()
or
not exists(getCSharpType(this.getType())) and
not exists(this.getType()) and
t0 instanceof ObjectType
)
}
@@ -96,16 +92,12 @@ private DataFlowCallable getEnclosingStaticFieldOrProperty(Expr e) {
private class ExprNodeImpl extends ExprNode, NodeImpl {
override DataFlowCallable getEnclosingCallableImpl() {
result.asCallable() =
[
this.getExpr().(CIL::Expr).getEnclosingCallable().(DotNet::Callable),
this.getControlFlowNodeImpl().getEnclosingCallable()
]
result.asCallable() = this.getControlFlowNodeImpl().getEnclosingCallable()
or
result = getEnclosingStaticFieldOrProperty(this.asExpr())
}
override DotNet::Type getTypeImpl() {
override Type getTypeImpl() {
forceCachingInSameStage() and
result = this.getExpr().getType()
}
@@ -121,11 +113,6 @@ private class ExprNodeImpl extends ExprNode, NodeImpl {
override string toStringImpl() {
forceCachingInSameStage() and
result = this.getControlFlowNodeImpl().toString()
or
exists(CIL::Expr e |
this = TCilExprNode(e) and
result = e.toString()
)
}
}
@@ -260,12 +247,6 @@ predicate hasNodePath(ControlFlowReachabilityConfiguration conf, ExprNode n1, No
)
}
/** Gets the CIL data-flow node for `node`, if any. */
CIL::DataFlowNode asCilDataFlowNode(Node node) {
result = node.asParameter() or
result = node.asExpr()
}
/** Provides logic related to captured variables. */
module VariableCapture {
private import codeql.dataflow.VariableCapture as Shared
@@ -731,79 +712,6 @@ module LocalFlow {
)
}
private module CilFlow {
/**
* Holds if `nodeFrom` is a last node referencing SSA definition `def`, which
* can reach `next`.
*/
private predicate localFlowCilSsaInput(
Node nodeFrom, CilSsaImpl::DefinitionExt def, CilSsaImpl::DefinitionExt next
) {
exists(CIL::BasicBlock bb, int i | CilSsaImpl::lastRefBeforeRedefExt(def, bb, i, next) |
def.definesAt(_, bb, i, _) and
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition() and
def != next
or
nodeFrom = TCilExprNode(bb.getNode(i).(CIL::ReadAccess))
)
}
/**
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
* CIL SSA definition `def`.
*/
private predicate localCilSsaFlowStep(CilSsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
// Flow into SSA definition
exists(CIL::VariableUpdate vu |
vu = def.(CilSsa::Definition).getVariableUpdate() and
vu.getSource() = asCilDataFlowNode(nodeFrom) and
def = nodeTo.(CilSsaDefinitionExtNode).getDefinition()
)
or
// Flow from SSA definition to first read
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition() and
nodeTo = TCilExprNode(CilSsaImpl::getAFirstReadExt(def))
or
// Flow from read to next read
exists(CIL::ReadAccess readFrom, CIL::ReadAccess readTo |
CilSsaImpl::hasAdjacentReadsExt(def, readFrom, readTo) and
nodeTo = TCilExprNode(readTo) and
nodeFrom = TCilExprNode(readFrom) and
nodeFrom != nodeTo
)
or
// Flow into phi (read) node
exists(CilSsaImpl::DefinitionExt phi |
localFlowCilSsaInput(nodeFrom, def, phi) and
phi = nodeTo.(CilSsaDefinitionExtNode).getDefinition()
|
phi instanceof CilSsa::PhiNode
or
phi instanceof CilSsaImpl::PhiReadNode
)
}
private predicate localExactStep(CIL::DataFlowNode src, CIL::DataFlowNode sink) {
src = sink.(CIL::Opcodes::Dup).getAnOperand()
or
src = sink.(CIL::Conversion).getExpr()
or
src = sink.(CIL::WriteAccess).getExpr()
or
src = sink.(CIL::Method).getAnImplementation().getAnInstruction().(CIL::Return)
or
src = sink.(CIL::Return).getExpr()
or
src = sink.(CIL::ConditionalBranch).getAnOperand()
}
predicate localFlowStepCil(Node nodeFrom, Node nodeTo) {
localExactStep(asCilDataFlowNode(nodeFrom), asCilDataFlowNode(nodeTo))
or
localCilSsaFlowStep(_, nodeFrom, nodeTo)
}
}
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
hasNodePath(any(LocalExprStepConfiguration x), nodeFrom, nodeTo)
or
@@ -812,8 +720,6 @@ module LocalFlow {
or
ThisFlow::adjacentThisRefs(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
or
CilFlow::localFlowStepCil(nodeFrom, nodeTo)
or
exists(AssignableDefinition def, ControlFlow::Node cfn, Ssa::ExplicitDefinition ssaDef |
ssaDef.getADefinition() = def and
ssaDef.getControlFlowNode() = cfn and
@@ -1115,13 +1021,6 @@ private predicate arrayStore(Expr e, Expr src, Expr a, boolean postUpdate) {
*/
private predicate arrayRead(Expr e1, ArrayRead e2) { e1 = e2.getQualifier() }
private Type getCSharpType(DotNet::Type t) {
result = t
or
not t instanceof Type and
result.matchesHandle(t)
}
private class RelevantGvnType extends Gvn::GvnType {
RelevantGvnType() { this = any(NodeImpl n).getDataFlowType().asGvnType() }
}
@@ -1193,8 +1092,6 @@ private module Cached {
cached
newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getAstNode() instanceof Expr } or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TCilSsaDefinitionExtNode(CilSsaImpl::DefinitionExt def) or
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) {
// Handled by `TExplicitParameterNode` below
not def.(Ssa::ExplicitDefinition).getADefinition() instanceof
@@ -1205,7 +1102,7 @@ private module Cached {
// Handled by `TExplicitParameterNode` below
not def instanceof AssignableDefinitions::ImplicitParameterDefinition
} or
TExplicitParameterNode(DotNet::Parameter p) {
TExplicitParameterNode(Parameter p) {
p = any(DataFlowCallable dfc).asCallable().getAParameter()
} or
TInstanceParameterNode(InstanceCallable c) or
@@ -1375,28 +1272,6 @@ predicate nodeIsHidden(Node n) {
n instanceof CaptureNode
}
/** A CIL SSA definition, viewed as a node in a data flow graph. */
class CilSsaDefinitionExtNode extends NodeImpl, TCilSsaDefinitionExtNode {
CilSsaImpl::DefinitionExt def;
CilSsaDefinitionExtNode() { this = TCilSsaDefinitionExtNode(def) }
/** Gets the underlying SSA definition. */
CilSsaImpl::DefinitionExt getDefinition() { result = def }
override DataFlowCallable getEnclosingCallableImpl() {
result.asCallable() = def.getBasicBlock().getFirstNode().getImplementation().getMethod()
}
override CIL::Type getTypeImpl() { result = def.getSourceVariable().getType() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
override Location getLocationImpl() { result = def.getBasicBlock().getLocation() }
override string toStringImpl() { result = def.toString() }
}
/** An SSA definition, viewed as a node in a data flow graph. */
class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
SsaImpl::DefinitionExt def;
@@ -1468,7 +1343,7 @@ private module ParameterNodes {
* flow graph.
*/
class ExplicitParameterNode extends ParameterNodeImpl, TExplicitParameterNode {
private DotNet::Parameter parameter;
private Parameter parameter;
ExplicitParameterNode() { this = TExplicitParameterNode(parameter) }
@@ -1486,7 +1361,7 @@ private module ParameterNodes {
result.asCallable() = parameter.getCallable()
}
override DotNet::Type getTypeImpl() { result = parameter.getType() }
override Type getTypeImpl() { result = parameter.getType() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
@@ -1543,7 +1418,7 @@ private module ParameterNodes {
override Location getLocationImpl() { result = callable.getLocation() }
override DotNet::Type getTypeImpl() { none() }
override Type getTypeImpl() { none() }
override DataFlowType getDataFlowType() { callable = result.asDelegate() }
@@ -1612,11 +1487,7 @@ private module ArgumentNodes {
/** A data-flow node that represents an explicit call argument. */
class ExplicitArgumentNode extends ArgumentNodeImpl {
ExplicitArgumentNode() {
this.asExpr() instanceof Argument
or
this.asExpr() = any(CilDataFlowCall cc).getCilCall().getAnArgument()
}
ExplicitArgumentNode() { this.asExpr() instanceof Argument }
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
exists(ArgumentConfiguration x, Expr c, Argument arg |
@@ -1625,12 +1496,6 @@ private module ArgumentNodes {
arg.isArgumentOf(c, pos) and
x.hasExprPath(_, this.getControlFlowNode(), _, call.getControlFlowNode())
)
or
exists(CIL::Call c, CIL::Expr arg |
arg = this.asExpr() and
c = call.getExpr() and
arg = c.getArgument(pos.getPosition())
)
}
}
@@ -1747,7 +1612,7 @@ private module ReturnNodes {
*/
class ExprReturnNode extends ReturnNode, ExprNode {
ExprReturnNode() {
exists(DotNet::Callable c, DotNet::Expr e | e = this.getExpr() |
exists(Callable c, Expr e | e = this.getExpr() |
c.canReturn(e) and not c.(Modifiable).isAsync()
)
}
@@ -1881,17 +1746,13 @@ private module OutNodes {
}
/**
* A data-flow node that reads a value returned directly by a callable,
* either via a C# call or a CIL call.
* A data-flow node that reads a value returned directly by a callable.
*/
class ExprOutNode extends OutNode, ExprNode {
private DataFlowCall call;
ExprOutNode() {
exists(DotNet::Expr e | e = this.getExpr() |
call = csharpCall(e, this.getControlFlowNode()) or
call = TCilCall(e)
)
exists(Expr e | e = this.getExpr() | call = csharpCall(e, this.getControlFlowNode()))
}
override DataFlowCall getCall(ReturnKind kind) {
@@ -1973,7 +1834,7 @@ class FlowSummaryNode extends NodeImpl, TFlowSummaryNode {
result = FlowSummaryImpl::Private::summaryNodeType(this.getSummaryNode())
}
override DotNet::Type getTypeImpl() { none() }
override Type getTypeImpl() { none() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
@@ -2134,8 +1995,6 @@ class FieldOrProperty extends Assignable, Modifiable {
or
p.isAutoImplementedReadOnly()
or
p.matchesHandle(any(CIL::TrivialProperty tp))
or
p.getDeclaringType() instanceof AnonymousClass
)
)
@@ -2740,7 +2599,7 @@ module PostUpdateNodes {
result = getEnclosingStaticFieldOrProperty(oc)
}
override DotNet::Type getTypeImpl() { result = oc.getType() }
override Type getTypeImpl() { result = oc.getType() }
override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() { result = cfn }
@@ -2853,7 +2712,7 @@ class CastNode extends Node {
}
}
class DataFlowExpr = DotNet::Expr;
class DataFlowExpr = Expr;
/** Holds if `e` is an expression that always has the same Boolean value `val`. */
private predicate constantBooleanExpr(Expr e, boolean val) {

View File

@@ -1,6 +1,4 @@
private import csharp
private import cil
private import dotnet
private import DataFlowDispatch
private import DataFlowPrivate
private import semmle.code.csharp.controlflow.Guards
@@ -12,7 +10,7 @@ private import semmle.code.csharp.Unification
*/
class Node extends TNode {
/** Gets the expression corresponding to this node, if any. */
DotNet::Expr asExpr() { result = this.(ExprNode).getExpr() }
Expr asExpr() { result = this.(ExprNode).getExpr() }
/**
* Gets the expression corresponding to this node, at control flow node `cfn`,
@@ -23,7 +21,7 @@ class Node extends TNode {
}
/** Gets the parameter corresponding to this node, if any. */
DotNet::Parameter asParameter() { result = this.(ParameterNode).getParameter() }
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
/** Gets the definition corresponding to this node, if any. */
AssignableDefinition asDefinition() { result = this.asDefinitionAtNode(_) }
@@ -37,7 +35,7 @@ class Node extends TNode {
}
/** Gets the type of this node. */
final DotNet::Type getType() { result = this.(NodeImpl).getTypeImpl() }
final Type getType() { result = this.(NodeImpl).getTypeImpl() }
/** Gets the enclosing callable of this node. */
final Callable getEnclosingCallable() {
@@ -67,8 +65,6 @@ class Node extends TNode {
}
}
private class TExprNode_ = TExprNode or TCilExprNode;
/**
* An expression, viewed as a node in a data flow graph.
*
@@ -76,13 +72,9 @@ private class TExprNode_ = TExprNode or TCilExprNode;
* to multiple `ExprNode`s, just like it may correspond to multiple
* `ControlFlow::Node`s.
*/
class ExprNode extends Node, TExprNode_ {
class ExprNode extends Node, TExprNode {
/** Gets the expression corresponding to this node. */
DotNet::Expr getExpr() {
result = this.getExprAtNode(_)
or
this = TCilExprNode(result)
}
Expr getExpr() { result = this.getExprAtNode(_) }
/**
* Gets the expression corresponding to this node, at control flow node `cfn`,
@@ -100,7 +92,7 @@ class ExprNode extends Node, TExprNode_ {
*/
class ParameterNode extends Node instanceof ParameterNodeImpl {
/** Gets the parameter corresponding to this node, if any. */
DotNet::Parameter getParameter() {
Parameter getParameter() {
exists(DataFlowCallable c, ParameterPosition ppos |
super.isParameterOf(c, ppos) and
result = c.asCallable().getParameter(ppos.getPosition())
@@ -120,12 +112,12 @@ class AssignableDefinitionNode extends Node instanceof AssignableDefinitionNodeI
}
/** Gets a node corresponding to expression `e`. */
ExprNode exprNode(DotNet::Expr e) { result.getExpr() = e }
ExprNode exprNode(Expr e) { result.getExpr() = e }
/**
* Gets the node corresponding to the value of parameter `p` at function entry.
*/
ParameterNode parameterNode(DotNet::Parameter p) { result.getParameter() = p }
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
/** Gets a node corresponding to the definition `def`. */
AssignableDefinitionNode assignableDefinitionNode(AssignableDefinition def) {
@@ -146,7 +138,7 @@ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprFlow(DotNet::Expr e1, DotNet::Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
/**
* A data flow node that jumps between callables. This can be extended in

View File

@@ -7,8 +7,6 @@ private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.dataflow.internal.ControlFlowReachability
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.commons.ComparisonTest
private import cil
private import dotnet
// import `TaintedMember` definitions from other files to avoid potential reevaluation
private import semmle.code.csharp.frameworks.JsonNET
private import semmle.code.csharp.frameworks.WCF
@@ -33,16 +31,6 @@ predicate defaultTaintSanitizer(DataFlow::Node node) {
bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
private predicate localCilTaintStep(CIL::DataFlowNode src, CIL::DataFlowNode sink) {
src = sink.(CIL::BinaryArithmeticExpr).getAnOperand() or
src = sink.(CIL::Opcodes::Neg).getOperand() or
src = sink.(CIL::UnaryBitwiseOperation).getOperand()
}
private predicate localTaintStepCil(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
localCilTaintStep(asCilDataFlowNode(nodeFrom), asCilDataFlowNode(nodeTo))
}
private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityConfiguration {
LocalTaintExprStepConfiguration() { this = "LocalTaintExprStepConfiguration" }
@@ -106,8 +94,6 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon
private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
hasNodePath(any(LocalTaintExprStepConfiguration x), nodeFrom, nodeTo)
or
localTaintStepCil(nodeFrom, nodeTo)
}
cached

View File

@@ -5,14 +5,12 @@
*/
import csharp
private import cil
private import dotnet
/**
* A run-time callable. That is, a callable that is neither abstract
* nor defined in an interface.
*/
class RuntimeCallable extends DotNet::Callable {
class RuntimeCallable extends Callable {
RuntimeCallable() {
not this.(Modifiable).isAbstract() and
(
@@ -24,13 +22,10 @@ class RuntimeCallable extends DotNet::Callable {
/** A run-time method. */
class RuntimeMethod extends RuntimeCallable {
RuntimeMethod() {
this instanceof Method or
this instanceof CIL::Method
}
RuntimeMethod() { this instanceof Method }
/** Holds if the method is `static`. */
predicate isStatic() { this.(Method).isStatic() or this.(CIL::Method).isStatic() }
predicate isStatic() { this.(Method).isStatic() }
}
/** A run-time instance method. */

View File

@@ -64,7 +64,7 @@ class Call extends Expr, @call {
* consider default arguments.
*/
cached
Expr getArgumentForParameter(DotNet::Parameter p) {
Expr getArgumentForParameter(Parameter p) {
// Appears in the positional part of the call
result = this.getImplicitArgument(p)
or
@@ -74,7 +74,7 @@ class Call extends Expr, @call {
}
pragma[noinline]
private Expr getImplicitArgument(DotNet::Parameter p) {
private Expr getImplicitArgument(Parameter p) {
this.getTarget().getAParameter() = p and
not exists(result.getExplicitArgumentName()) and
(

View File

@@ -18,7 +18,6 @@ import semmle.code.csharp.controlflow.ControlFlowElement
import semmle.code.csharp.Location
import semmle.code.csharp.Stmt
import semmle.code.csharp.Type
private import dotnet
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.TypeRef
@@ -950,13 +949,13 @@ class InterpolatedStringExpr extends Expr, @interpolated_string_expr {
* A `throw` element. Either a `throw` expression (`ThrowExpr`)
* or a `throw` statement (`ThrowStmt`).
*/
class ThrowElement extends ControlFlowElement, DotNet::Throw, @throw_element {
class ThrowElement extends ControlFlowElement, @throw_element {
/**
* Gets the expression of the exception being thrown, if any.
*
* For example, `new Exception("Syntax error")` in `throw new Exception("Syntax error");`.
*/
override Expr getExpr() { result = this.getChild(0) }
Expr getExpr() { result = this.getChild(0) }
/** Gets the type of exception being thrown. */
Class getThrownExceptionType() {

View File

@@ -5,7 +5,6 @@
*/
import Expr
private import dotnet
/**
* A literal. Either a Boolean literal (`BoolLiteral`), a Unicode character
@@ -13,7 +12,7 @@ private import dotnet
* point literal (`RealLiteral`), a `string` literal (`StringLiteral`), or a
* `null` literal (`NullLiteral`).
*/
class Literal extends DotNet::Literal, Expr, @literal_expr {
class Literal extends Expr, @literal_expr {
override string toString() { result = this.getValue() }
}
@@ -43,7 +42,7 @@ class CharLiteral extends Literal, @char_literal_expr {
* literal (`LongLiteral`), a `uint` literal (`UIntLiteral`), or a `ulong`
* literal (`ULongLiteral`).
*/
class IntegerLiteral extends DotNet::IntLiteral, Literal, @integer_literal_expr { }
class IntegerLiteral extends Literal, @integer_literal_expr { }
/**
* An `int` literal, for example `0`.
@@ -105,7 +104,7 @@ class DecimalLiteral extends RealLiteral, @decimal_literal_expr {
* A `string` literal. Either a `string` literal (`StringLiteralUtf16`),
* or a `u8` literal (`StringLiteralUtf8`).
*/
class StringLiteral extends DotNet::StringLiteral, Literal, @string_literal_expr {
class StringLiteral extends Literal, @string_literal_expr {
override string toString() { result = "\"" + this.getValue().replaceAll("\"", "\\\"") + "\"" }
override string getAPrimaryQlClass() { result = "StringLiteral" }
@@ -128,6 +127,6 @@ class StringLiteralUtf8 extends StringLiteral, @utf8_string_literal_expr {
/**
* A `null` literal.
*/
class NullLiteral extends DotNet::NullLiteral, Literal, @null_literal_expr {
class NullLiteral extends Literal, @null_literal_expr {
override string getAPrimaryQlClass() { result = "NullLiteral" }
}

View File

@@ -1,5 +1,4 @@
private import csharp
private import dotnet
pragma[nomagic]
private predicate isTestNamespace(Namespace ns) {

View File

@@ -3,7 +3,6 @@
*/
private import csharp as CS
private import dotnet
private import semmle.code.csharp.commons.Util as Util
private import semmle.code.csharp.commons.Collections as Collections
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
@@ -62,7 +61,7 @@ predicate isRelevantForTypeBasedFlowModels = isRelevantForModels/1;
* In the Standard library and 3rd party libraries it the callables that can be called
* from outside the library itself.
*/
class TargetApiSpecific extends DotNet::Callable {
class TargetApiSpecific extends CS::Callable {
TargetApiSpecific() {
this.fromSource() and
this.isUnboundDeclaration()

View File

@@ -1,5 +1,4 @@
private import csharp
private import dotnet
private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.frameworks.system.linq.Expressions
@@ -21,14 +20,14 @@ private predicate genericCollectionType(ValueOrRefType t, TypeParameter tp) {
/**
* Holds if `tp` is a type parameter of the immediate type declaring `callable`.
*/
private predicate classTypeParameter(DotNet::Callable callable, TypeParameter tp) {
private predicate classTypeParameter(Callable callable, TypeParameter tp) {
callable.getDeclaringType().(UnboundGeneric).getATypeParameter() = tp
}
/**
* Holds if `tp` is type parameter of `callable` or the type declaring `callable`.
*/
private predicate localTypeParameter(DotNet::Callable callable, TypeParameter tp) {
private predicate localTypeParameter(Callable callable, TypeParameter tp) {
classTypeParameter(callable, tp) or
callable.(UnboundGeneric).getATypeParameter() = tp
}
@@ -37,7 +36,7 @@ private predicate localTypeParameter(DotNet::Callable callable, TypeParameter tp
* Holds if `callable` has a parameter of type `tp`
* or collection parameterized over type `tp`.
*/
private predicate parameter(DotNet::Callable callable, string input, TypeParameter tp) {
private predicate parameter(Callable callable, string input, TypeParameter tp) {
exists(Parameter p |
input = Specific::parameterAccess(p) and
p = callable.getAParameter() and
@@ -62,7 +61,7 @@ private string getSyntheticField(TypeParameter tp) {
* Gets a models as data string representation of, how a value of type `tp`
* can be read or stored implicitly in relation to `callable`.
*/
private string implicit(DotNet::Callable callable, TypeParameter tp) {
private string implicit(Callable callable, TypeParameter tp) {
classTypeParameter(callable, tp) and
not callable.(Modifiable).isStatic() and
exists(string access |
@@ -77,7 +76,7 @@ private string implicit(DotNet::Callable callable, TypeParameter tp) {
/**
* Holds if `callable` has a delegate parameter `dt` at parameter position `position`.
*/
private predicate delegate(DotNet::Callable callable, DelegateType dt, int position) {
private predicate delegate(Callable callable, DelegateType dt, int position) {
exists(Parameter p |
p = callable.getAParameter() and
dt = p.getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() and
@@ -93,7 +92,7 @@ private predicate delegate(DotNet::Callable callable, DelegateType dt, int posit
* in every disjunction.
*/
bindingset[callable]
private string getAccess(DotNet::Callable callable, Type return, TypeParameter tp) {
private string getAccess(Callable callable, Type return, TypeParameter tp) {
return = tp and result = ""
or
genericCollectionType(return, tp) and result = ".Element"
@@ -111,7 +110,7 @@ private string getAccess(DotNet::Callable callable, Type return, TypeParameter t
* Holds if `input` is a models as data string representation of, how a value of type `tp`
* (or a generic parameterized over `tp`) can be generated by a delegate parameter of `callable`.
*/
private predicate delegateSource(DotNet::Callable callable, string input, TypeParameter tp) {
private predicate delegateSource(Callable callable, string input, TypeParameter tp) {
exists(DelegateType dt, int position, Type return, string access |
delegate(callable, dt, position) and
return = dt.getReturnType() and
@@ -129,7 +128,7 @@ private predicate delegateSource(DotNet::Callable callable, string input, TypePa
* (2) The parameters of `callable`.
* (3) Any delegate parameters of `callable`.
*/
private predicate input(DotNet::Callable callable, string input, TypeParameter tp) {
private predicate input(Callable callable, string input, TypeParameter tp) {
input = implicit(callable, tp)
or
parameter(callable, input, tp)
@@ -141,7 +140,7 @@ private predicate input(DotNet::Callable callable, string input, TypeParameter t
* Holds if `callable` returns a value of type `tp` (or a generic parameterized over `tp`) and `output`
* is a models as data string representation of, how data is routed to the return.
*/
private predicate returns(DotNet::Callable callable, TypeParameter tp, string output) {
private predicate returns(Callable callable, TypeParameter tp, string output) {
exists(Type return, string access | return = callable.getReturnType() |
access = getAccess(callable, return, tp) and
output = "ReturnValue" + access
@@ -153,7 +152,7 @@ private predicate returns(DotNet::Callable callable, TypeParameter tp, string ou
* and `output` is the models as data string representation of, how data is routed to
* the delegate parameter.
*/
private predicate delegateSink(DotNet::Callable callable, TypeParameter tp, string output) {
private predicate delegateSink(Callable callable, TypeParameter tp, string output) {
exists(DelegateType dt, int position, Parameter p |
delegate(callable, dt, position) and
p = dt.getAParameter() and
@@ -170,7 +169,7 @@ private predicate delegateSink(DotNet::Callable callable, TypeParameter tp, stri
* (2) The return of `callable`.
* (3) Any delegate parameters of `callable`.
*/
private predicate output(DotNet::Callable callable, TypeParameter tp, string output) {
private predicate output(Callable callable, TypeParameter tp, string output) {
output = implicit(callable, tp)
or
returns(callable, tp, output)