Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7e89e57

Browse files
authored
Merge pull request #4606 from hvitved/csharp/dataflow/ef
C#: Precise data flow for EntityFramework(Core)
2 parents 26286e5 + 697b0ba commit 7e89e57

16 files changed

Lines changed: 1334 additions & 149 deletions

csharp/ql/src/semmle/code/csharp/dataflow/FlowSummary.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private import internal.FlowSummarySpecific::Private
88
private import internal.DataFlowPublic as DataFlowPublic
99
// import all instances below
1010
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
11+
private import semmle.code.csharp.frameworks.EntityFramework
1112

1213
class SummarizableCallable = Impl::Public::SummarizableCallable;
1314

@@ -135,6 +136,17 @@ module SummaryOutput {
135136
result = TDelegateSummaryOutput(i, j) and
136137
hasDelegateArgumentPosition2(c, i, j)
137138
}
139+
140+
/**
141+
* Gets an output specification that specifies the `output` of `target` as the
142+
* output. That is, data will flow into one callable and out of another callable
143+
* (`target`).
144+
*
145+
* `output` is limited to (this) parameters and ordinary returns.
146+
*/
147+
SummaryOutput jump(SummarizableCallable target, SummaryOutput output) {
148+
result = TJumpSummaryOutput(target, toReturnKind(output))
149+
}
138150
}
139151

140152
class SummarizedCallable = Impl::Public::SummarizedCallable;

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ DotNet::Callable getCallableForDataFlow(DotNet::Callable c) {
2121
result = sourceDecl and
2222
result instanceof SummarizedCallable
2323
or
24+
result = sourceDecl and
25+
FlowSummaryImpl::Private::summary(_, _, _, SummaryOutput::jump(result, _), _, _)
26+
or
2427
result.hasBody() and
2528
if sourceDecl.getFile().fromSource()
2629
then

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -469,12 +469,9 @@ private predicate overridesOrImplementsSourceDecl(Property p1, Property p2) {
469469
private predicate fieldOrPropertyRead(Expr e1, Content c, FieldOrPropertyRead e2) {
470470
e1 = e2.getQualifier() and
471471
exists(FieldOrProperty ret | c = ret.getContent() |
472-
ret.isFieldLike() and
473472
ret = e2.getTarget()
474473
or
475-
exists(ContentList cl, Property target |
476-
FlowSummaryImpl::Private::summary(_, _, _, _, cl, _) and
477-
cl.contains(ret.getContent()) and
474+
exists(Property target |
478475
target.getGetter() = e2.(PropertyCall).getARuntimeTarget() and
479476
overridesOrImplementsSourceDecl(target, ret)
480477
)
@@ -640,6 +637,10 @@ private module Cached {
640637
output = SummaryOutput::delegate(delegateIndex, parameterIndex)
641638
)
642639
} or
640+
TSummaryJumpNode(SummarizedCallable c, SummarizableCallable target, ReturnKind rk) {
641+
FlowSummaryImpl::Private::summary(c, _, _,
642+
FlowSummarySpecific::Private::TJumpSummaryOutput(target, rk), _, _)
643+
} or
643644
TParamsArgumentNode(ControlFlow::Node callCfn) {
644645
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
645646
}
@@ -685,8 +686,19 @@ private module Cached {
685686
* taken into account.
686687
*/
687688
cached
688-
predicate jumpStepImpl(ExprNode pred, ExprNode succ) {
689+
predicate jumpStepImpl(Node pred, Node succ) {
689690
pred.(NonLocalJumpNode).getAJumpSuccessor(true) = succ
691+
or
692+
exists(FieldOrProperty fl, FieldOrPropertyRead flr |
693+
fl.isStatic() and
694+
fl.isFieldLike() and
695+
fl.getAnAssignedValue() = pred.asExpr() and
696+
fl.getAnAccess() = flr and
697+
flr = succ.asExpr() and
698+
flr.hasNonlocalValue()
699+
)
700+
or
701+
succ = pred.(SummaryJumpNode).getAJumpTarget()
690702
}
691703

692704
cached
@@ -1613,6 +1625,28 @@ private class SummaryInternalNode extends SummaryNodeImpl, TSummaryInternalNode
16131625
override string toStringImpl() { result = "[summary] " + state + " in " + c }
16141626
}
16151627

1628+
/** A data-flow node used to model flow summaries with jumps. */
1629+
private class SummaryJumpNode extends SummaryNodeImpl, TSummaryJumpNode {
1630+
private SummarizedCallable c;
1631+
private SummarizableCallable target;
1632+
private ReturnKind rk;
1633+
1634+
SummaryJumpNode() { this = TSummaryJumpNode(c, target, rk) }
1635+
1636+
/** Gets a jump target of this node. */
1637+
OutNode getAJumpTarget() { target = viableCallable(result.getCall(rk)) }
1638+
1639+
override Callable getEnclosingCallableImpl() { result = c }
1640+
1641+
override DotNet::Type getTypeImpl() { result = target.getReturnType() }
1642+
1643+
override ControlFlow::Node getControlFlowNodeImpl() { none() }
1644+
1645+
override Location getLocationImpl() { result = c.getLocation() }
1646+
1647+
override string toStringImpl() { result = "[summary] jump to " + target }
1648+
}
1649+
16161650
/** A field or a property. */
16171651
class FieldOrProperty extends Assignable, Modifiable {
16181652
FieldOrProperty() {
@@ -1669,26 +1703,6 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
16691703
}
16701704
}
16711705

1672-
/** A write to a static field/property. */
1673-
private class StaticFieldLikeJumpNode extends NonLocalJumpNode, ExprNode {
1674-
FieldOrProperty fl;
1675-
FieldOrPropertyRead flr;
1676-
ExprNode succ;
1677-
1678-
StaticFieldLikeJumpNode() {
1679-
fl.isStatic() and
1680-
fl.isFieldLike() and
1681-
fl.getAnAssignedValue() = this.getExpr() and
1682-
fl.getAnAccess() = flr and
1683-
flr = succ.getExpr() and
1684-
flr.hasNonlocalValue()
1685-
}
1686-
1687-
override ExprNode getAJumpSuccessor(boolean preservesValue) {
1688-
result = succ and preservesValue = true
1689-
}
1690-
}
1691-
16921706
predicate jumpStep = jumpStepImpl/2;
16931707

16941708
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {

csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummarySpecific.qll

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
private import csharp
66
private import semmle.code.csharp.frameworks.system.linq.Expressions
7+
private import DataFlowDispatch
78

89
module Private {
910
private import Public
1011
private import DataFlowPrivate as DataFlowPrivate
1112
private import DataFlowPublic as DataFlowPublic
1213
private import FlowSummaryImpl as Impl
13-
private import DataFlowDispatch
1414
private import semmle.code.csharp.Unification
1515

1616
class Content = DataFlowPublic::Content;
@@ -56,7 +56,19 @@ module Private {
5656
TParameterSummaryOutput(int i) {
5757
i in [-1, any(SummarizableCallable c).getAParameter().getPosition()]
5858
} or
59-
TDelegateSummaryOutput(int i, int j) { hasDelegateArgumentPosition2(_, i, j) }
59+
TDelegateSummaryOutput(int i, int j) { hasDelegateArgumentPosition2(_, i, j) } or
60+
TJumpSummaryOutput(SummarizableCallable target, ReturnKind rk) {
61+
rk instanceof NormalReturnKind and
62+
(
63+
target instanceof Constructor or
64+
not target.getReturnType() instanceof VoidType
65+
)
66+
or
67+
rk instanceof QualifierReturnKind and
68+
not target.(Modifiable).isStatic()
69+
or
70+
exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
71+
}
6072

6173
/** Gets the return kind that matches `sink`, if any. */
6274
ReturnKind toReturnKind(SummaryOutput output) {
@@ -92,6 +104,11 @@ module Private {
92104
output = TDelegateSummaryOutput(i, j) and
93105
result = DataFlowPrivate::TSummaryDelegateArgumentNode(c, i, j)
94106
)
107+
or
108+
exists(SummarizableCallable target, ReturnKind rk |
109+
output = TJumpSummaryOutput(target, rk) and
110+
result = DataFlowPrivate::TSummaryJumpNode(c, target, rk)
111+
)
95112
}
96113

97114
/** Gets the internal summary node for the given values. */
@@ -151,6 +168,11 @@ module Public {
151168
this = TDelegateSummaryOutput(delegateIndex, parameterIndex) and
152169
result = "parameter " + parameterIndex + " of delegate parameter " + delegateIndex
153170
)
171+
or
172+
exists(SummarizableCallable target, ReturnKind rk |
173+
this = TJumpSummaryOutput(target, rk) and
174+
result = "jump to " + target + " (" + rk + ")"
175+
)
154176
}
155177
}
156178
}

0 commit comments

Comments
 (0)