Skip to content

Commit 755085e

Browse files
committed
C#: Introduce ParameterPosition and ArgumentPosition
1 parent b40c77d commit 755085e

File tree

10 files changed

+357
-211
lines changed

10 files changed

+357
-211
lines changed

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

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
import csharp
44
private import internal.FlowSummaryImpl as Impl
5-
private import internal.DataFlowDispatch
5+
private import internal.DataFlowDispatch as DataFlowDispatch
6+
7+
class ParameterPosition = DataFlowDispatch::ParameterPosition;
8+
9+
class ArgumentPosition = DataFlowDispatch::ArgumentPosition;
610

711
// import all instances below
812
private module Summaries {
@@ -14,7 +18,27 @@ class SummaryComponent = Impl::Public::SummaryComponent;
1418

1519
/** Provides predicates for constructing summary components. */
1620
module SummaryComponent {
17-
import Impl::Public::SummaryComponent
21+
private import Impl::Public::SummaryComponent as SummaryComponentInternal
22+
23+
predicate content = SummaryComponentInternal::content/1;
24+
25+
/** Gets a summary component for parameter `i`. */
26+
SummaryComponent parameter(int i) {
27+
exists(ArgumentPosition pos |
28+
result = SummaryComponentInternal::parameter(pos) and
29+
i = pos.getPosition()
30+
)
31+
}
32+
33+
/** Gets a summary component for argument `i`. */
34+
SummaryComponent argument(int i) {
35+
exists(ParameterPosition pos |
36+
result = SummaryComponentInternal::argument(pos) and
37+
i = pos.getPosition()
38+
)
39+
}
40+
41+
predicate return = SummaryComponentInternal::return/1;
1842

1943
/** Gets a summary component that represents a qualifier. */
2044
SummaryComponent qualifier() { result = argument(-1) }
@@ -33,14 +57,14 @@ module SummaryComponent {
3357
}
3458

3559
/** Gets a summary component that represents the return value of a call. */
36-
SummaryComponent return() { result = return(any(NormalReturnKind rk)) }
60+
SummaryComponent return() { result = return(any(DataFlowDispatch::NormalReturnKind rk)) }
3761

3862
/** Gets a summary component that represents a jump to `c`. */
3963
SummaryComponent jump(Callable c) {
4064
result =
41-
return(any(JumpReturnKind jrk |
65+
return(any(DataFlowDispatch::JumpReturnKind jrk |
4266
jrk.getTarget() = c.getUnboundDeclaration() and
43-
jrk.getTargetReturnKind() instanceof NormalReturnKind
67+
jrk.getTargetReturnKind() instanceof DataFlowDispatch::NormalReturnKind
4468
))
4569
}
4670
}
@@ -49,7 +73,16 @@ class SummaryComponentStack = Impl::Public::SummaryComponentStack;
4973

5074
/** Provides predicates for constructing stacks of summary components. */
5175
module SummaryComponentStack {
52-
import Impl::Public::SummaryComponentStack
76+
private import Impl::Public::SummaryComponentStack as SummaryComponentStackInternal
77+
78+
predicate singleton = SummaryComponentStackInternal::singleton/1;
79+
80+
predicate push = SummaryComponentStackInternal::push/2;
81+
82+
/** Gets a singleton stack for argument `i`. */
83+
SummaryComponentStack argument(int i) { result = singleton(SummaryComponent::argument(i)) }
84+
85+
predicate return = SummaryComponentStackInternal::return/1;
5386

5487
/** Gets a singleton stack representing a qualifier. */
5588
SummaryComponentStack qualifier() { result = singleton(SummaryComponent::qualifier()) }
@@ -84,12 +117,12 @@ private class SummarizedCallableDefaultClearsContent extends Impl::Public::Summa
84117
}
85118

86119
// By default, we assume that all stores into arguments are definite
87-
override predicate clearsContent(int i, DataFlow::Content content) {
120+
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
88121
exists(SummaryComponentStack output |
89122
this.propagatesFlow(_, output, _) and
90123
output.drop(_) =
91124
SummaryComponentStack::push(SummaryComponent::content(content),
92-
SummaryComponentStack::argument(i)) and
125+
SummaryComponentStack::argument(pos.getPosition())) and
93126
not content instanceof DataFlow::ElementContent
94127
)
95128
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,10 +465,10 @@ private module FrameworkDataFlowAdaptor {
465465
)
466466
}
467467

468-
override predicate clearsContent(int i, Content content) {
468+
override predicate clearsContent(ParameterPosition pos, Content content) {
469469
exists(SummaryComponentStack input |
470470
ltdf.clearsContent(toCallableFlowSource(input), content, this) and
471-
input = SummaryComponentStack::singleton(SummaryComponent::argument(i))
471+
input = SummaryComponentStack::argument(pos.getPosition())
472472
)
473473
}
474474
}

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

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ private import DataFlowImplCommon as DataFlowImplCommon
55
private import DataFlowPublic
66
private import DataFlowPrivate
77
private import FlowSummaryImpl as FlowSummaryImpl
8-
private import semmle.code.csharp.dataflow.FlowSummary
8+
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
99
private import semmle.code.csharp.dataflow.ExternalFlow
1010
private import semmle.code.csharp.dispatch.Dispatch
1111
private import semmle.code.csharp.dispatch.RuntimeCallable
1212
private import semmle.code.csharp.frameworks.system.Collections
1313
private import semmle.code.csharp.frameworks.system.collections.Generic
1414

1515
private predicate summarizedCallable(DataFlowCallable c) {
16-
c instanceof SummarizedCallable
16+
c instanceof FlowSummary::SummarizedCallable
1717
or
1818
FlowSummaryImpl::Private::summaryReturnNode(_, TJumpReturnKind(c, _))
1919
or
@@ -108,13 +108,27 @@ private module Cached {
108108
// No need to include calls that are compiled from source
109109
not call.getImplementation().getMethod().compiledFromSource()
110110
} or
111-
TSummaryCall(SummarizedCallable c, Node receiver) {
111+
TSummaryCall(FlowSummary::SummarizedCallable c, Node receiver) {
112112
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
113113
}
114114

115115
/** Gets a viable run-time target for the call `call`. */
116116
cached
117117
DataFlowCallable viableCallable(DataFlowCall call) { result = call.getARuntimeTarget() }
118+
119+
private int parameterPosition() {
120+
result =
121+
[
122+
-1, any(Parameter p).getPosition(),
123+
ImplicitCapturedParameterNodeImpl::getParameterPosition(_)
124+
]
125+
}
126+
127+
cached
128+
newtype TParameterPosition = MkParameterPosition(int i) { i = parameterPosition() }
129+
130+
cached
131+
newtype TArgumentPosition = MkArgumentPosition(int i) { i = parameterPosition() }
118132
}
119133

120134
import Cached
@@ -388,7 +402,7 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
388402
* the method `Select`.
389403
*/
390404
class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
391-
private SummarizedCallable c;
405+
private FlowSummary::SummarizedCallable c;
392406
private Node receiver;
393407

394408
SummaryCall() { this = TSummaryCall(c, receiver) }
@@ -410,3 +424,37 @@ class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
410424

411425
override Location getLocation() { result = c.getLocation() }
412426
}
427+
428+
/** A parameter position represented by an integer. */
429+
class ParameterPosition extends MkParameterPosition {
430+
private int i;
431+
432+
ParameterPosition() { this = MkParameterPosition(i) }
433+
434+
/** Gets the underlying integer. */
435+
int getPosition() { result = i }
436+
437+
/** Gets a textual representation of this position. */
438+
string toString() { result = i.toString() }
439+
}
440+
441+
/** An argument position represented by an integer. */
442+
class ArgumentPosition extends MkArgumentPosition {
443+
private int i;
444+
445+
ArgumentPosition() { this = MkArgumentPosition(i) }
446+
447+
/** Gets the underlying integer. */
448+
int getPosition() { result = i }
449+
450+
/** Gets a textual representation of this position. */
451+
string toString() { result = i.toString() }
452+
}
453+
454+
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
455+
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
456+
exists(int i |
457+
ppos = MkParameterPosition(i) and
458+
apos = MkArgumentPosition(i)
459+
)
460+
}

0 commit comments

Comments
 (0)