Skip to content

Commit 20af134

Browse files
authored
Merge pull request #9210 from michaelnebel/dataflow/summarizedcallablerefactor
DataFlow - SummarizedCallable refactor
2 parents 3407b0f + 3ebd4af commit 20af134

File tree

22 files changed

+130
-211
lines changed

22 files changed

+130
-211
lines changed

csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,7 @@ Element interpretElement(
515515
/**
516516
* Holds if `c` has a `generated` summary.
517517
*/
518-
predicate hasSummary(Callable c, boolean generated) {
519-
exists(DataFlowCallable dc |
520-
dc.asSummarizedCallable() = c and summaryElement(dc, _, _, _, generated)
521-
)
522-
}
518+
predicate hasSummary(Callable c, boolean generated) { summaryElement(c, _, _, _, generated) }
523519

524520
cached
525521
private module Cached {

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

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -114,69 +114,7 @@ module SummaryComponentStack {
114114
SummaryComponentStack jump(Callable c) { result = singleton(SummaryComponent::jump(c)) }
115115
}
116116

117-
/**
118-
* A class for synthesized callables given by a summary.
119-
*/
120-
abstract class SummarizedCallable extends DotNet::Callable {
121-
SummarizedCallable() { this.isUnboundDeclaration() }
122-
123-
/**
124-
* Holds if data may flow from `input` to `output` through this callable.
125-
*
126-
* `preservesValue` indicates whether this is a value-preserving step
127-
* or a taint-step.
128-
*
129-
* Input specifications are restricted to stacks that end with
130-
* `SummaryComponent::argument(_)`, preceded by zero or more
131-
* `SummaryComponent::return(_)` or `SummaryComponent::content(_)` components.
132-
*
133-
* Output specifications are restricted to stacks that end with
134-
* `SummaryComponent::return(_)` or `SummaryComponent::argument(_)`.
135-
*
136-
* Output stacks ending with `SummaryComponent::return(_)` can be preceded by zero
137-
* or more `SummaryComponent::content(_)` components.
138-
*
139-
* Output stacks ending with `SummaryComponent::argument(_)` can be preceded by an
140-
* optional `SummaryComponent::parameter(_)` component, which in turn can be preceded
141-
* by zero or more `SummaryComponent::content(_)` components.
142-
*/
143-
pragma[nomagic]
144-
predicate propagatesFlow(
145-
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
146-
) {
147-
none()
148-
}
149-
150-
/**
151-
* Holds if values stored inside `content` are cleared on objects passed as
152-
* arguments at position `pos` to this callable.
153-
*/
154-
pragma[nomagic]
155-
predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) { none() }
156-
157-
/**
158-
* Holds if the summary is auto generated.
159-
*/
160-
predicate isAutoGenerated() { none() }
161-
}
162-
163-
private class SummarizedCallableAdapter extends Impl::Public::SummarizedCallable {
164-
private SummarizedCallable sc;
165-
166-
SummarizedCallableAdapter() { this = DataFlowDispatch::TSummarizedCallable(sc) }
167-
168-
final override predicate propagatesFlow(
169-
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
170-
) {
171-
sc.propagatesFlow(input, output, preservesValue)
172-
}
173-
174-
final override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
175-
sc.clearsContent(pos, content)
176-
}
177-
178-
final override predicate isAutoGenerated() { sc.isAutoGenerated() }
179-
}
117+
class SummarizedCallable = Impl::Public::SummarizedCallable;
180118

181119
private predicate recordConstructorFlow(Constructor c, int i, Property p) {
182120
c = any(RecordType r).getAMember() and

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
457457

458458
override DataFlow::Node getNode() { none() }
459459

460-
override DataFlowCallable getEnclosingCallable() { result = c }
460+
override DataFlowCallable getEnclosingCallable() { result.asSummarizedCallable() = c }
461461

462462
override string toString() { result = "[summary] call to " + receiver + " in " + c }
463463

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -976,17 +976,15 @@ private module ParameterNodes {
976976
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
977977

978978
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
979-
sc = c and pos = pos_
979+
sc = c.asSummarizedCallable() and pos = pos_
980980
}
981981

982-
override DataFlowCallable getEnclosingCallableImpl() { result = sc }
982+
override DataFlowCallable getEnclosingCallableImpl() { result.asSummarizedCallable() = sc }
983983

984984
override Type getTypeImpl() {
985-
exists(int i |
986-
pos_.getPosition() = i and result = sc.asSummarizedCallable().getParameter(i).getType()
987-
)
985+
exists(int i | pos_.getPosition() = i and result = sc.getParameter(i).getType())
988986
or
989-
pos_.isThisParameter() and result = sc.asSummarizedCallable().getDeclaringType()
987+
pos_.isThisParameter() and result = sc.getDeclaringType()
990988
}
991989

992990
override ControlFlow::Node getControlFlowNodeImpl() { none() }
@@ -1464,7 +1462,7 @@ class SummaryNode extends NodeImpl, TSummaryNode {
14641462

14651463
SummaryNode() { this = TSummaryNode(c, state) }
14661464

1467-
override DataFlowCallable getEnclosingCallableImpl() { result = c }
1465+
override DataFlowCallable getEnclosingCallableImpl() { result.asSummarizedCallable() = c }
14681466

14691467
override DataFlowType getDataFlowType() {
14701468
result = FlowSummaryImpl::Private::summaryNodeType(this)

csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ module Public {
195195
}
196196

197197
/** A callable with a flow summary. */
198-
abstract class SummarizedCallable extends DataFlowCallable {
198+
abstract class SummarizedCallable extends SummarizedCallableBase {
199+
bindingset[this]
200+
SummarizedCallable() { any() }
201+
199202
/**
200203
* Holds if data may flow from `input` to `output` through this callable.
201204
*
@@ -493,7 +496,7 @@ module Private {
493496
or
494497
exists(ParameterPosition pos |
495498
parameterReadState(c, state, pos) and
496-
result.(ParamNode).isParameterOf(c, pos)
499+
result.(ParamNode).isParameterOf(inject(c), pos)
497500
)
498501
)
499502
}
@@ -621,7 +624,7 @@ module Private {
621624
predicate summaryPostUpdateNode(Node post, Node pre) {
622625
exists(SummarizedCallable c, ParameterPosition pos |
623626
isParameterPostUpdate(post, c, pos) and
624-
pre.(ParamNode).isParameterOf(c, pos)
627+
pre.(ParamNode).isParameterOf(inject(c), pos)
625628
)
626629
or
627630
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -644,7 +647,7 @@ module Private {
644647
* node, and back out to `p`.
645648
*/
646649
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
647-
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
650+
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
648651
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
649652
summary(c, inputContents, outputContents, _) and
650653
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -748,8 +751,11 @@ module Private {
748751
private predicate viableParam(
749752
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
750753
) {
751-
p.isParameterOf(sc, ppos) and
752-
sc = viableCallable(call)
754+
exists(DataFlowCallable c |
755+
c = inject(sc) and
756+
p.isParameterOf(c, ppos) and
757+
c = viableCallable(call)
758+
)
753759
}
754760

755761
pragma[nomagic]
@@ -1067,16 +1073,18 @@ module Private {
10671073
/** Provides a query predicate for outputting a set of relevant flow summaries. */
10681074
module TestOutput {
10691075
/** A flow summary to include in the `summary/3` query predicate. */
1070-
abstract class RelevantSummarizedCallable extends SummarizedCallable {
1076+
abstract class RelevantSummarizedCallable instanceof SummarizedCallable {
10711077
/** Gets the string representation of this callable used by `summary/1`. */
10721078
abstract string getCallableCsv();
10731079

10741080
/** Holds if flow is propagated between `input` and `output`. */
10751081
predicate relevantSummary(
10761082
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
10771083
) {
1078-
this.propagatesFlow(input, output, preservesValue)
1084+
super.propagatesFlow(input, output, preservesValue)
10791085
}
1086+
1087+
string toString() { result = super.toString() }
10801088
}
10811089

10821090
/** Render the kind in the format used in flow summaries. */
@@ -1087,7 +1095,7 @@ module Private {
10871095
}
10881096

10891097
private string renderGenerated(RelevantSummarizedCallable c) {
1090-
if c.isAutoGenerated() then result = "generated:" else result = ""
1098+
if c.(SummarizedCallable).isAutoGenerated() then result = "generated:" else result = ""
10911099
}
10921100

10931101
/**
@@ -1117,19 +1125,21 @@ module Private {
11171125
*/
11181126
module RenderSummarizedCallable {
11191127
/** A summarized callable to include in the graph. */
1120-
abstract class RelevantSummarizedCallable extends SummarizedCallable { }
1128+
abstract class RelevantSummarizedCallable instanceof SummarizedCallable {
1129+
string toString() { result = super.toString() }
1130+
}
11211131

11221132
private newtype TNodeOrCall =
11231133
MkNode(Node n) {
11241134
exists(RelevantSummarizedCallable c |
11251135
n = summaryNode(c, _)
11261136
or
1127-
n.(ParamNode).isParameterOf(c, _)
1137+
n.(ParamNode).isParameterOf(inject(c), _)
11281138
)
11291139
} or
11301140
MkCall(DataFlowCall call) {
11311141
call = summaryDataFlowCall(_) and
1132-
call.getEnclosingCallable() instanceof RelevantSummarizedCallable
1142+
call.getEnclosingCallable() = inject(any(RelevantSummarizedCallable c))
11331143
}
11341144

11351145
private class NodeOrCall extends TNodeOrCall {

csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ private import semmle.code.csharp.Unification
1515
private import semmle.code.csharp.dataflow.ExternalFlow
1616
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
1717

18+
class SummarizedCallableBase extends Callable {
19+
SummarizedCallableBase() { this.isUnboundDeclaration() }
20+
}
21+
22+
DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c }
23+
1824
/** Gets the parameter position of the instance parameter. */
1925
ArgumentPosition instanceParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks
2026

@@ -55,7 +61,7 @@ private DataFlowType getReturnTypeBase(DotNet::Callable c, ReturnKind rk) {
5561
/** Gets the return type of kind `rk` for callable `c`. */
5662
bindingset[c]
5763
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
58-
result = getReturnTypeBase(c.asSummarizedCallable(), rk)
64+
result = getReturnTypeBase(c, rk)
5965
or
6066
rk =
6167
any(JumpReturnKind jrk | result = getReturnTypeBase(jrk.getTarget(), jrk.getTargetReturnKind()))
@@ -85,9 +91,12 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
8591
)
8692
}
8793

88-
private predicate summaryElement0(
89-
DotNet::Callable c, string input, string output, string kind, boolean generated
90-
) {
94+
/**
95+
* Holds if an external flow summary exists for `c` with input specification
96+
* `input`, output specification `output`, kind `kind`, and a flag `generated`
97+
* stating whether the summary is autogenerated.
98+
*/
99+
predicate summaryElement(Callable c, string input, string output, string kind, boolean generated) {
91100
exists(
92101
string namespace, string type, boolean subtypes, string name, string signature, string ext
93102
|
@@ -96,21 +105,6 @@ private predicate summaryElement0(
96105
)
97106
}
98107

99-
private class SummarizedCallableExternal extends FlowSummary::SummarizedCallable {
100-
SummarizedCallableExternal() { summaryElement0(this, _, _, _, _) }
101-
}
102-
103-
/**
104-
* Holds if an external flow summary exists for `c` with input specification
105-
* `input`, output specification `output`, kind `kind`, and a flag `generated`
106-
* stating whether the summary is autogenerated.
107-
*/
108-
predicate summaryElement(
109-
DataFlowCallable c, string input, string output, string kind, boolean generated
110-
) {
111-
summaryElement0(c.asSummarizedCallable(), input, output, kind, generated)
112-
}
113-
114108
/**
115109
* Holds if an external source specification exists for `e` with output specification
116110
* `output`, kind `kind`, and a flag `generated` stating whether the source specification is

csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ module EntityFramework {
8888
}
8989

9090
/** A flow summary for EntityFramework. */
91-
abstract class EFSummarizedCallable extends SummarizedCallable { }
91+
abstract class EFSummarizedCallable extends SummarizedCallable {
92+
bindingset[this]
93+
EFSummarizedCallable() { any() }
94+
}
9295

9396
private class DbSetAddOrUpdateRequiredSummaryComponentStack extends RequiredSummaryComponentStack {
9497
override predicate required(SummaryComponent head, SummaryComponentStack tail) {

csharp/ql/test/library-tests/dataflow/external-models/steps.ql

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ query predicate summarySetterStep(DataFlow::Node arg, DataFlow::Node out, Conten
4242
FlowSummaryImpl::Private::Steps::summarySetterStep(arg, c, out)
4343
}
4444

45-
query predicate clearsContent(
46-
FlowSummaryImpl::Public::SummarizedCallable c, DataFlow::Content k, ParameterPosition pos
47-
) {
45+
query predicate clearsContent(SummarizedCallable c, DataFlow::Content k, ParameterPosition pos) {
4846
c.clearsContent(pos, k) and
49-
c.asSummarizedCallable().fromSource()
47+
c.fromSource()
5048
}

csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.ql

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ private import semmle.code.csharp.dataflow.internal.DataFlowPrivate::Csv
33
private import semmle.code.csharp.dataflow.ExternalFlow
44

55
class IncludeFilteredSummarizedCallable extends IncludeSummarizedCallable {
6-
IncludeFilteredSummarizedCallable() { exists(this) }
6+
IncludeFilteredSummarizedCallable() { this instanceof SummarizedCallable }
77

88
/**
99
* Holds if flow is propagated between `input` and `output` and
@@ -13,12 +13,11 @@ class IncludeFilteredSummarizedCallable extends IncludeSummarizedCallable {
1313
override predicate relevantSummary(
1414
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
1515
) {
16-
this.propagatesFlow(input, output, preservesValue) and
17-
not exists(IncludeSummarizedCallable rsc, SummarizedCallable sc |
18-
sc = rsc.asSummarizedCallable() and
19-
isBaseCallableOrPrototype(sc) and
20-
rsc.propagatesFlow(input, output, preservesValue) and
21-
this.asSummarizedCallable().(UnboundCallable).overridesOrImplementsUnbound(sc)
16+
this.(SummarizedCallable).propagatesFlow(input, output, preservesValue) and
17+
not exists(IncludeSummarizedCallable rsc |
18+
isBaseCallableOrPrototype(rsc) and
19+
rsc.(SummarizedCallable).propagatesFlow(input, output, preservesValue) and
20+
this.(UnboundCallable).overridesOrImplementsUnbound(rsc)
2221
)
2322
}
2423
}

csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import shared.FlowSummaries
33
import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
44

55
private class IncludeEFSummarizedCallable extends IncludeSummarizedCallable {
6-
IncludeEFSummarizedCallable() { this.asSummarizedCallable() instanceof EFSummarizedCallable }
6+
IncludeEFSummarizedCallable() { this instanceof EFSummarizedCallable }
77
}
88

99
query predicate sourceNode(DataFlow::Node node, string kind) {

0 commit comments

Comments
 (0)