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

Skip to content

Commit f4d1d73

Browse files
committed
C#: Shared interface/implementation for flow summaries
1 parent 104ff5d commit f4d1d73

8 files changed

Lines changed: 949 additions & 390 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* Provides classes and predicates for definining flow summaries.
3+
*/
4+
5+
import csharp
6+
private import internal.FlowSummaryImpl as Impl
7+
private import internal.FlowSummarySpecific::Private
8+
private import internal.DataFlowPublic as DataFlowPublic
9+
// import all instances below
10+
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
11+
12+
class SummarizableCallable = Impl::Public::SummarizableCallable;
13+
14+
/** An unbound method. */
15+
class SummarizableMethod extends SummarizableCallable, Method { }
16+
17+
class ContentList = Impl::Public::ContentList;
18+
19+
/** Provides predicates for constructing content lists. */
20+
module ContentList {
21+
import Impl::Public::ContentList
22+
23+
/** Gets the singleton "element content" content list. */
24+
ContentList element() { result = singleton(any(DataFlowPublic::ElementContent c)) }
25+
26+
/** Gets a singleton property content list. */
27+
ContentList property(Property p) {
28+
result =
29+
singleton(any(DataFlowPublic::PropertyContent c | c.getProperty() = p.getSourceDeclaration()))
30+
}
31+
32+
/** Gets a singleton field content list. */
33+
ContentList field(Field f) {
34+
result =
35+
singleton(any(DataFlowPublic::FieldContent c | c.getField() = f.getSourceDeclaration()))
36+
}
37+
}
38+
39+
class SummaryInput = Impl::Public::SummaryInput;
40+
41+
/** Provides predicates for constructing flow-summary input specifications */
42+
module SummaryInput {
43+
private import semmle.code.csharp.frameworks.system.Collections
44+
45+
/**
46+
* Gets an input specification that specifies the `i`th parameter as
47+
* the input.
48+
*/
49+
SummaryInput parameter(int i) { result = TParameterSummaryInput(i) }
50+
51+
private predicate isCollectionType(ValueOrRefType t) {
52+
t.getABaseType*() instanceof SystemCollectionsIEnumerableInterface and
53+
not t instanceof StringType
54+
}
55+
56+
/**
57+
* Gets an input specification that specifies the `i`th parameter as
58+
* the input.
59+
*
60+
* `inputContents` is either empty or a singleton element content list,
61+
* depending on whether the type of the `i`th parameter of `c` is a
62+
* collection type.
63+
*/
64+
SummaryInput parameter(SummarizableCallable c, int i, ContentList inputContents) {
65+
result = parameter(i) and
66+
exists(Parameter p |
67+
p = c.getParameter(i) and
68+
if isCollectionType(p.getType())
69+
then inputContents = ContentList::element()
70+
else inputContents = ContentList::empty()
71+
)
72+
}
73+
74+
/**
75+
* Gets an input specification that specifies the implicit `this` parameter
76+
* as the input.
77+
*/
78+
SummaryInput thisParameter() { result = TParameterSummaryInput(-1) }
79+
80+
/**
81+
* Gets an input specification that specifies output from the delegate at
82+
* parameter `i` as the input.
83+
*/
84+
SummaryInput delegate(int i) { result = TDelegateSummaryInput(i) }
85+
86+
/**
87+
* Gets an input specification that specifies output from the delegate at
88+
* parameter `i` as the input.
89+
*
90+
* `c` must be a compatible callable, that is, a callable where the `i`th
91+
* parameter is a delegate.
92+
*/
93+
SummaryInput delegate(SummarizableCallable c, int i) {
94+
result = delegate(i) and
95+
hasDelegateArgumentPosition(c, i)
96+
}
97+
}
98+
99+
class SummaryOutput = Impl::Public::SummaryOutput;
100+
101+
/** Provides predicates for constructing flow-summary output specifications. */
102+
module SummaryOutput {
103+
/**
104+
* Gets an output specification that specifies the return value from a call as
105+
* the output.
106+
*/
107+
SummaryOutput return() { result = TReturnSummaryOutput() }
108+
109+
/**
110+
* Gets an output specification that specifies the `i`th parameter as the
111+
* output.
112+
*/
113+
SummaryOutput parameter(int i) { result = TParameterSummaryOutput(i) }
114+
115+
/**
116+
* Gets an output specification that specifies the implicit `this` parameter
117+
* as the output.
118+
*/
119+
SummaryOutput thisParameter() { result = TParameterSummaryOutput(-1) }
120+
121+
/**
122+
* Gets an output specification that specifies parameter `j` of the delegate at
123+
* parameter `i` as the output.
124+
*/
125+
SummaryOutput delegate(int i, int j) { result = TDelegateSummaryOutput(i, j) }
126+
127+
/**
128+
* Gets an output specification that specifies parameter `j` of the delegate at
129+
* parameter `i` as the output.
130+
*
131+
* `c` must be a compatible callable, that is, a callable where the `i`th
132+
* parameter is a delegate with a parameter at position `j`.
133+
*/
134+
SummaryOutput delegate(SummarizableCallable c, int i, int j) {
135+
result = TDelegateSummaryOutput(i, j) and
136+
hasDelegateArgumentPosition2(c, i, j)
137+
}
138+
}
139+
140+
class SummarizedCallable = Impl::Public::SummarizedCallable;

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

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ private import semmle.code.csharp.dataflow.internal.DelegateDataFlow
2222
// import `LibraryTypeDataFlow` definitions from other files to avoid potential reevaluation
2323
private import semmle.code.csharp.frameworks.EntityFramework
2424
private import semmle.code.csharp.frameworks.JsonNET
25+
private import FlowSummary
2526

2627
private newtype TAccessPath =
2728
TNilAccessPath() or
@@ -353,6 +354,90 @@ abstract class LibraryTypeDataFlow extends Type {
353354
}
354355
}
355356

357+
private CallableFlowSource toCallableFlowSource(SummaryInput input) {
358+
result = TCallableFlowSourceQualifier() and
359+
input = SummaryInput::parameter(-1)
360+
or
361+
exists(int i |
362+
result = TCallableFlowSourceArg(i) and
363+
input = SummaryInput::parameter(i)
364+
)
365+
or
366+
exists(int i |
367+
result = TCallableFlowSourceDelegateArg(i) and
368+
input = SummaryInput::delegate(i)
369+
)
370+
}
371+
372+
private CallableFlowSink toCallableFlowSink(SummaryOutput output) {
373+
result = TCallableFlowSinkQualifier() and
374+
output = SummaryOutput::parameter(-1)
375+
or
376+
result = TCallableFlowSinkReturn() and
377+
output = SummaryOutput::return()
378+
or
379+
exists(int i |
380+
result = TCallableFlowSinkArg(i) and
381+
output = SummaryOutput::parameter(i)
382+
)
383+
or
384+
exists(int i, int j |
385+
result = TCallableFlowSinkDelegateArg(i, j) and
386+
output = SummaryOutput::delegate(i, j)
387+
)
388+
}
389+
390+
private AccessPath toAccessPath(ContentList cl) {
391+
cl = ContentList::empty() and
392+
result = TNilAccessPath()
393+
or
394+
exists(Content head, ContentList tail |
395+
cl = ContentList::cons(head, tail) and
396+
result = TConsAccessPath(head, toAccessPath(tail))
397+
)
398+
}
399+
400+
private class FrameworkDataFlowAdaptor extends SummarizedCallable {
401+
private LibraryTypeDataFlow ltdf;
402+
403+
FrameworkDataFlowAdaptor() {
404+
ltdf.callableFlow(_, _, this, _) or
405+
ltdf.callableFlow(_, _, _, _, this, _) or
406+
ltdf.clearsContent(_, _, this)
407+
}
408+
409+
override predicate propagatesFlow(SummaryInput input, SummaryOutput output, boolean preservesValue) {
410+
ltdf.callableFlow(toCallableFlowSource(input), toCallableFlowSink(output), this, preservesValue)
411+
}
412+
413+
override predicate propagatesFlow(
414+
SummaryInput input, ContentList inputContents, SummaryOutput output, ContentList outputContents,
415+
boolean preservesValue
416+
) {
417+
ltdf
418+
.callableFlow(toCallableFlowSource(input), toAccessPath(inputContents),
419+
toCallableFlowSink(output), toAccessPath(outputContents), this, preservesValue)
420+
}
421+
422+
private AccessPath getAnAccessPath() {
423+
ltdf.callableFlow(_, result, _, _, this, _)
424+
or
425+
ltdf.callableFlow(_, _, _, result, _, _)
426+
}
427+
428+
override predicate requiresContentList(Content head, ContentList tail) {
429+
exists(AccessPath ap |
430+
ap = this.getAnAccessPath().drop(_) and
431+
head = ap.getHead() and
432+
toAccessPath(tail) = ap.getTail()
433+
)
434+
}
435+
436+
override predicate clearsContent(SummaryInput input, Content content) {
437+
ltdf.clearsContent(toCallableFlowSource(input), content, this)
438+
}
439+
}
440+
356441
/** Data flow for `System.Int32`. */
357442
class SystemInt32Flow extends LibraryTypeDataFlow, SystemInt32Struct {
358443
override predicate callableFlow(

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ private import cil
33
private import dotnet
44
private import DataFlowPrivate
55
private import DelegateDataFlow
6-
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
6+
private import FlowSummaryImpl as FlowSummaryImpl
7+
private import semmle.code.csharp.dataflow.FlowSummary
78
private import semmle.code.csharp.dispatch.Dispatch
89
private import semmle.code.csharp.frameworks.system.Collections
910
private import semmle.code.csharp.frameworks.system.collections.Generic
@@ -18,7 +19,7 @@ private import semmle.code.csharp.frameworks.system.collections.Generic
1819
DotNet::Callable getCallableForDataFlow(DotNet::Callable c) {
1920
exists(DotNet::Callable sourceDecl | sourceDecl = c.getSourceDeclaration() |
2021
result = sourceDecl and
21-
Summaries::summary(result, _, _, _, _, _)
22+
result instanceof SummarizedCallable
2223
or
2324
result.hasBody() and
2425
if sourceDecl.getFile().fromSource()
@@ -107,15 +108,15 @@ private module Cached {
107108
// No need to include calls that are compiled from source
108109
not call.getImplementation().getMethod().compiledFromSource()
109110
} or
110-
TSummaryDelegateCall(SourceDeclarationCallable c, int pos) {
111-
exists(CallableFlowSourceDelegateArg source |
112-
Summaries::summary(c, source, _, _, _, _) and
113-
pos = source.getArgumentIndex()
111+
TSummaryDelegateCall(SummarizedCallable c, int pos) {
112+
exists(SummaryInput input |
113+
FlowSummaryImpl::Private::summary(c, input, _, _, _, _) and
114+
input = SummaryInput::delegate(pos)
114115
)
115116
or
116-
exists(CallableFlowSinkDelegateArg sink |
117-
Summaries::summary(c, _, _, sink, _, _) and
118-
pos = sink.getDelegateIndex()
117+
exists(SummaryOutput output |
118+
FlowSummaryImpl::Private::summary(c, _, _, output, _, _) and
119+
output = SummaryOutput::delegate(pos, _)
119120
)
120121
}
121122

@@ -381,7 +382,7 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
381382
* the method `Select`.
382383
*/
383384
class SummaryDelegateCall extends DelegateDataFlowCall, TSummaryDelegateCall {
384-
private SourceDeclarationCallable c;
385+
private SummarizedCallable c;
385386
private int pos;
386387

387388
SummaryDelegateCall() { this = TSummaryDelegateCall(c, pos) }

0 commit comments

Comments
 (0)