|
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