|
1 | | -/** |
2 | | - * Provides classes and predicates for definining flow summaries. |
3 | | - */ |
| 1 | +/** Provides classes and predicates for defining flow summaries. */ |
4 | 2 |
|
5 | 3 | import csharp |
6 | 4 | 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 | | -private import semmle.code.csharp.frameworks.EntityFramework |
| 5 | +private import internal.DataFlowDispatch |
12 | 6 |
|
13 | | -class SummarizableCallable = Impl::Public::SummarizableCallable; |
| 7 | +// import all instances below |
| 8 | +private module Summaries { |
| 9 | + private import semmle.code.csharp.dataflow.LibraryTypeDataFlow |
| 10 | + private import semmle.code.csharp.frameworks.EntityFramework |
| 11 | +} |
14 | 12 |
|
15 | | -/** An unbound method. */ |
16 | | -class SummarizableMethod extends SummarizableCallable, Method { } |
| 13 | +class SummaryComponent = Impl::Public::SummaryComponent; |
17 | 14 |
|
18 | | -class ContentList = Impl::Public::ContentList; |
| 15 | +/** Provides predicates for constructing summary components. */ |
| 16 | +module SummaryComponent { |
| 17 | + import Impl::Public::SummaryComponent |
19 | 18 |
|
20 | | -/** Provides predicates for constructing content lists. */ |
21 | | -module ContentList { |
22 | | - import Impl::Public::ContentList |
| 19 | + /** Gets a summary component that represents a qualifier. */ |
| 20 | + SummaryComponent qualifier() { result = argument(-1) } |
23 | 21 |
|
24 | | - /** Gets the singleton "element content" content list. */ |
25 | | - ContentList element() { result = singleton(any(DataFlowPublic::ElementContent c)) } |
| 22 | + /** Gets a summary component that represents an element in a collection. */ |
| 23 | + SummaryComponent element() { result = content(any(DataFlow::ElementContent c)) } |
26 | 24 |
|
27 | | - /** Gets a singleton property content list. */ |
28 | | - ContentList property(Property p) { |
29 | | - result = |
30 | | - singleton(any(DataFlowPublic::PropertyContent c | c.getProperty() = p.getUnboundDeclaration())) |
| 25 | + /** Gets a summary component for property `p`. */ |
| 26 | + SummaryComponent property(Property p) { |
| 27 | + result = content(any(DataFlow::PropertyContent c | c.getProperty() = p.getUnboundDeclaration())) |
31 | 28 | } |
32 | 29 |
|
33 | | - /** Gets a singleton field content list. */ |
34 | | - ContentList field(Field f) { |
35 | | - result = |
36 | | - singleton(any(DataFlowPublic::FieldContent c | c.getField() = f.getUnboundDeclaration())) |
| 30 | + /** Gets a summary component for field `f`. */ |
| 31 | + SummaryComponent field(Field f) { |
| 32 | + result = content(any(DataFlow::FieldContent c | c.getField() = f.getUnboundDeclaration())) |
37 | 33 | } |
38 | | -} |
39 | | - |
40 | | -class SummaryInput = Impl::Public::SummaryInput; |
41 | 34 |
|
42 | | -/** Provides predicates for constructing flow-summary input specifications */ |
43 | | -module SummaryInput { |
44 | | - private import semmle.code.csharp.frameworks.system.Collections |
| 35 | + /** Gets a summary component that represents the return value of a call. */ |
| 36 | + SummaryComponent return() { result = return(any(NormalReturnKind rk)) } |
45 | 37 |
|
46 | 38 | /** |
47 | | - * Gets an input specification that specifies the `i`th parameter as |
48 | | - * the input. |
| 39 | + * Gets a summary component that represents the return value through the `i`th |
| 40 | + * `out` argument of a call. |
49 | 41 | */ |
50 | | - SummaryInput parameter(int i) { result = TParameterSummaryInput(i) } |
51 | | - |
52 | | - private predicate isCollectionType(ValueOrRefType t) { |
53 | | - t.getABaseType*() instanceof SystemCollectionsIEnumerableInterface and |
54 | | - not t instanceof StringType |
| 42 | + SummaryComponent outArgument(int i) { |
| 43 | + result = return(any(OutReturnKind rk | rk.getPosition() = i)) |
55 | 44 | } |
56 | 45 |
|
57 | 46 | /** |
58 | | - * Gets an input specification that specifies the `i`th parameter as |
59 | | - * the input. |
60 | | - * |
61 | | - * `inputContents` is either empty or a singleton element content list, |
62 | | - * depending on whether the type of the `i`th parameter of `c` is a |
63 | | - * collection type. |
| 47 | + * Gets a summary component that represents the return value through the `i`th |
| 48 | + * `ref` argument of a call. |
64 | 49 | */ |
65 | | - SummaryInput parameter(SummarizableCallable c, int i, ContentList inputContents) { |
66 | | - result = parameter(i) and |
67 | | - exists(Parameter p | |
68 | | - p = c.getParameter(i) and |
69 | | - if isCollectionType(p.getType()) |
70 | | - then inputContents = ContentList::element() |
71 | | - else inputContents = ContentList::empty() |
72 | | - ) |
| 50 | + SummaryComponent refArgument(int i) { |
| 51 | + result = return(any(RefReturnKind rk | rk.getPosition() = i)) |
73 | 52 | } |
74 | 53 |
|
75 | | - /** |
76 | | - * Gets an input specification that specifies the implicit `this` parameter |
77 | | - * as the input. |
78 | | - */ |
79 | | - SummaryInput thisParameter() { result = TParameterSummaryInput(-1) } |
80 | | - |
81 | | - /** |
82 | | - * Gets an input specification that specifies output from the delegate at |
83 | | - * parameter `i` as the input. |
84 | | - */ |
85 | | - SummaryInput delegate(int i) { result = TDelegateSummaryInput(i) } |
86 | | - |
87 | | - /** |
88 | | - * Gets an input specification that specifies output from the delegate at |
89 | | - * parameter `i` as the input. |
90 | | - * |
91 | | - * `c` must be a compatible callable, that is, a callable where the `i`th |
92 | | - * parameter is a delegate. |
93 | | - */ |
94 | | - SummaryInput delegate(SummarizableCallable c, int i) { |
95 | | - result = delegate(i) and |
96 | | - hasDelegateArgumentPosition(c, i) |
| 54 | + /** Gets a summary component that represents a jump to `c`. */ |
| 55 | + SummaryComponent jump(Callable c) { |
| 56 | + result = |
| 57 | + return(any(JumpReturnKind jrk | |
| 58 | + jrk.getTarget() = c.getUnboundDeclaration() and |
| 59 | + jrk.getTargetReturnKind() instanceof NormalReturnKind |
| 60 | + )) |
97 | 61 | } |
98 | 62 | } |
99 | 63 |
|
100 | | -class SummaryOutput = Impl::Public::SummaryOutput; |
| 64 | +class SummaryComponentStack = Impl::Public::SummaryComponentStack; |
101 | 65 |
|
102 | | -/** Provides predicates for constructing flow-summary output specifications. */ |
103 | | -module SummaryOutput { |
104 | | - /** |
105 | | - * Gets an output specification that specifies the return value from a call as |
106 | | - * the output. |
107 | | - */ |
108 | | - SummaryOutput return() { result = TReturnSummaryOutput() } |
| 66 | +/** Provides predicates for constructing stacks of summary components. */ |
| 67 | +module SummaryComponentStack { |
| 68 | + import Impl::Public::SummaryComponentStack |
109 | 69 |
|
110 | | - /** |
111 | | - * Gets an output specification that specifies the `i`th parameter as the |
112 | | - * output. |
113 | | - */ |
114 | | - SummaryOutput parameter(int i) { result = TParameterSummaryOutput(i) } |
| 70 | + /** Gets a singleton stack representing a qualifier. */ |
| 71 | + SummaryComponentStack qualifier() { result = singleton(SummaryComponent::qualifier()) } |
115 | 72 |
|
116 | | - /** |
117 | | - * Gets an output specification that specifies the implicit `this` parameter |
118 | | - * as the output. |
119 | | - */ |
120 | | - SummaryOutput thisParameter() { result = TParameterSummaryOutput(-1) } |
| 73 | + /** Gets a stack representing an element of `container`. */ |
| 74 | + SummaryComponentStack elementOf(SummaryComponentStack container) { |
| 75 | + result = push(SummaryComponent::element(), container) |
| 76 | + } |
121 | 77 |
|
122 | | - /** |
123 | | - * Gets an output specification that specifies parameter `j` of the delegate at |
124 | | - * parameter `i` as the output. |
125 | | - */ |
126 | | - SummaryOutput delegate(int i, int j) { result = TDelegateSummaryOutput(i, j) } |
| 78 | + /** Gets a stack representing a propery `p` of `object`. */ |
| 79 | + SummaryComponentStack propertyOf(Property p, SummaryComponentStack object) { |
| 80 | + result = push(SummaryComponent::property(p), object) |
| 81 | + } |
| 82 | + |
| 83 | + /** Gets a stack representing a field `f` of `object`. */ |
| 84 | + SummaryComponentStack fieldOf(Field f, SummaryComponentStack object) { |
| 85 | + result = push(SummaryComponent::field(f), object) |
| 86 | + } |
| 87 | + |
| 88 | + /** Gets a singleton stack representing the return value of a call. */ |
| 89 | + SummaryComponentStack return() { result = singleton(SummaryComponent::return()) } |
127 | 90 |
|
128 | 91 | /** |
129 | | - * Gets an output specification that specifies parameter `j` of the delegate at |
130 | | - * parameter `i` as the output. |
131 | | - * |
132 | | - * `c` must be a compatible callable, that is, a callable where the `i`th |
133 | | - * parameter is a delegate with a parameter at position `j`. |
| 92 | + * Gets a singleton stack representing the return value through the `i`th |
| 93 | + * `out` argument of a call. |
134 | 94 | */ |
135 | | - SummaryOutput delegate(SummarizableCallable c, int i, int j) { |
136 | | - result = TDelegateSummaryOutput(i, j) and |
137 | | - hasDelegateArgumentPosition2(c, i, j) |
138 | | - } |
| 95 | + SummaryComponentStack outArgument(int i) { result = singleton(SummaryComponent::outArgument(i)) } |
139 | 96 |
|
140 | 97 | /** |
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. |
| 98 | + * Gets a singleton stack representing the return value through the `i`th |
| 99 | + * `ref` argument of a call. |
146 | 100 | */ |
147 | | - SummaryOutput jump(SummarizableCallable target, SummaryOutput output) { |
148 | | - result = TJumpSummaryOutput(target, toReturnKind(output)) |
149 | | - } |
| 101 | + SummaryComponentStack refArgument(int i) { result = singleton(SummaryComponent::refArgument(i)) } |
| 102 | + |
| 103 | + /** Gets a singleton stack representing a jump to `c`. */ |
| 104 | + SummaryComponentStack jump(Callable c) { result = singleton(SummaryComponent::jump(c)) } |
150 | 105 | } |
151 | 106 |
|
152 | 107 | class SummarizedCallable = Impl::Public::SummarizedCallable; |
153 | 108 |
|
154 | | -/** Provides a query predicate for outputting a set of relevant flow summaries. */ |
155 | | -module TestOutput { |
156 | | - /** A flow summary to include in the `summary/3` query predicate. */ |
157 | | - abstract class RelevantSummarizedCallable extends SummarizedCallable { } |
158 | | - |
159 | | - /** A query predicate for outputting flow summaries in QL tests. */ |
160 | | - query predicate summary(string callable, string flow, boolean preservesValue) { |
161 | | - exists( |
162 | | - RelevantSummarizedCallable c, SummaryInput input, ContentList inputContents, |
163 | | - string inputContentsString, SummaryOutput output, ContentList outputContents, |
164 | | - string outputContentsString |
165 | | - | |
166 | | - callable = c.getQualifiedNameWithTypes() and |
167 | | - Impl::Private::summary(c, input, inputContents, output, outputContents, preservesValue) and |
168 | | - ( |
169 | | - if inputContents.length() = 0 |
170 | | - then inputContentsString = "" |
171 | | - else inputContentsString = " [" + inputContents + "]" |
172 | | - ) and |
173 | | - ( |
174 | | - if outputContents.length() = 0 |
175 | | - then outputContentsString = "" |
176 | | - else outputContentsString = " [" + outputContents + "]" |
177 | | - ) and |
178 | | - flow = input + inputContentsString + " -> " + output + outputContentsString |
179 | | - ) |
180 | | - } |
181 | | -} |
| 109 | +class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack; |
0 commit comments