|
3 | 3 | * data-flow classes and predicates. |
4 | 4 | */ |
5 | 5 |
|
6 | | -private import DataFlowImplSpecific::Private |
7 | | -private import DataFlowImplSpecific::Public |
8 | | -private import tainttracking1.TaintTrackingParameter::Private |
9 | | -private import tainttracking1.TaintTrackingParameter::Public |
10 | | - |
11 | | -module Consistency { |
12 | | - private newtype TConsistencyConfiguration = MkConsistencyConfiguration() |
13 | | - |
14 | | - /** A class for configuring the consistency queries. */ |
15 | | - class ConsistencyConfiguration extends TConsistencyConfiguration { |
16 | | - string toString() { none() } |
17 | | - |
18 | | - /** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */ |
19 | | - predicate uniqueEnclosingCallableExclude(Node n) { none() } |
20 | | - |
21 | | - /** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */ |
22 | | - predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() } |
23 | | - |
24 | | - /** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */ |
25 | | - predicate uniqueNodeLocationExclude(Node n) { none() } |
26 | | - |
27 | | - /** Holds if `n` should be excluded from the consistency test `missingLocation`. */ |
28 | | - predicate missingLocationExclude(Node n) { none() } |
29 | | - |
30 | | - /** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */ |
31 | | - predicate postWithInFlowExclude(Node n) { none() } |
32 | | - |
33 | | - /** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */ |
34 | | - predicate argHasPostUpdateExclude(ArgumentNode n) { none() } |
35 | | - |
36 | | - /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ |
37 | | - predicate reverseReadExclude(Node n) { none() } |
38 | | - |
39 | | - /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ |
40 | | - predicate postHasUniquePreExclude(PostUpdateNode n) { none() } |
41 | | - |
42 | | - /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ |
43 | | - predicate uniquePostUpdateExclude(Node n) { none() } |
44 | | - |
45 | | - /** Holds if `(call, ctx)` should be excluded from the consistency test `viableImplInCallContextTooLargeExclude`. */ |
46 | | - predicate viableImplInCallContextTooLargeExclude( |
47 | | - DataFlowCall call, DataFlowCall ctx, DataFlowCallable callable |
48 | | - ) { |
49 | | - none() |
50 | | - } |
51 | | - |
52 | | - /** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodeAtPosition`. */ |
53 | | - predicate uniqueParameterNodeAtPositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) { |
54 | | - none() |
55 | | - } |
56 | | - |
57 | | - /** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodePosition`. */ |
58 | | - predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) { |
59 | | - none() |
60 | | - } |
61 | | - |
62 | | - /** Holds if `n` should be excluded from the consistency test `identityLocalStep`. */ |
63 | | - predicate identityLocalStepExclude(Node n) { none() } |
64 | | - } |
65 | | - |
66 | | - private class RelevantNode extends Node { |
67 | | - RelevantNode() { |
68 | | - this instanceof ArgumentNode or |
69 | | - this instanceof ParameterNode or |
70 | | - this instanceof ReturnNode or |
71 | | - this = getAnOutNode(_, _) or |
72 | | - simpleLocalFlowStep(this, _) or |
73 | | - simpleLocalFlowStep(_, this) or |
74 | | - jumpStep(this, _) or |
75 | | - jumpStep(_, this) or |
76 | | - storeStep(this, _, _) or |
77 | | - storeStep(_, _, this) or |
78 | | - readStep(this, _, _) or |
79 | | - readStep(_, _, this) or |
80 | | - defaultAdditionalTaintStep(this, _) or |
81 | | - defaultAdditionalTaintStep(_, this) |
82 | | - } |
83 | | - } |
84 | | - |
85 | | - query predicate uniqueEnclosingCallable(Node n, string msg) { |
86 | | - exists(int c | |
87 | | - n instanceof RelevantNode and |
88 | | - c = count(nodeGetEnclosingCallable(n)) and |
89 | | - c != 1 and |
90 | | - not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and |
91 | | - msg = "Node should have one enclosing callable but has " + c + "." |
92 | | - ) |
93 | | - } |
94 | | - |
95 | | - query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) { |
96 | | - exists(int c | |
97 | | - c = count(call.getEnclosingCallable()) and |
98 | | - c != 1 and |
99 | | - not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and |
100 | | - msg = "Call should have one enclosing callable but has " + c + "." |
101 | | - ) |
102 | | - } |
103 | | - |
104 | | - query predicate uniqueType(Node n, string msg) { |
105 | | - exists(int c | |
106 | | - n instanceof RelevantNode and |
107 | | - c = count(getNodeType(n)) and |
108 | | - c != 1 and |
109 | | - msg = "Node should have one type but has " + c + "." |
110 | | - ) |
111 | | - } |
112 | | - |
113 | | - query predicate uniqueNodeLocation(Node n, string msg) { |
114 | | - exists(int c | |
115 | | - c = |
116 | | - count(string filepath, int startline, int startcolumn, int endline, int endcolumn | |
117 | | - n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) |
118 | | - ) and |
119 | | - c != 1 and |
120 | | - not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and |
121 | | - msg = "Node should have one location but has " + c + "." |
122 | | - ) |
123 | | - } |
124 | | - |
125 | | - query predicate missingLocation(string msg) { |
126 | | - exists(int c | |
127 | | - c = |
128 | | - strictcount(Node n | |
129 | | - not n.hasLocationInfo(_, _, _, _, _) and |
130 | | - not any(ConsistencyConfiguration conf).missingLocationExclude(n) |
131 | | - ) and |
132 | | - msg = "Nodes without location: " + c |
133 | | - ) |
134 | | - } |
135 | | - |
136 | | - query predicate uniqueNodeToString(Node n, string msg) { |
137 | | - exists(int c | |
138 | | - c = count(n.toString()) and |
139 | | - c != 1 and |
140 | | - msg = "Node should have one toString but has " + c + "." |
141 | | - ) |
142 | | - } |
143 | | - |
144 | | - query predicate missingToString(string msg) { |
145 | | - exists(int c | |
146 | | - c = strictcount(Node n | not exists(n.toString())) and |
147 | | - msg = "Nodes without toString: " + c |
148 | | - ) |
149 | | - } |
150 | | - |
151 | | - query predicate parameterCallable(ParameterNode p, string msg) { |
152 | | - exists(DataFlowCallable c | isParameterNode(p, c, _) and c != nodeGetEnclosingCallable(p)) and |
153 | | - msg = "Callable mismatch for parameter." |
154 | | - } |
155 | | - |
156 | | - query predicate localFlowIsLocal(Node n1, Node n2, string msg) { |
157 | | - simpleLocalFlowStep(n1, n2) and |
158 | | - nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and |
159 | | - msg = "Local flow step does not preserve enclosing callable." |
160 | | - } |
161 | | - |
162 | | - query predicate readStepIsLocal(Node n1, Node n2, string msg) { |
163 | | - readStep(n1, _, n2) and |
164 | | - nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and |
165 | | - msg = "Read step does not preserve enclosing callable." |
166 | | - } |
167 | | - |
168 | | - query predicate storeStepIsLocal(Node n1, Node n2, string msg) { |
169 | | - storeStep(n1, _, n2) and |
170 | | - nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and |
171 | | - msg = "Store step does not preserve enclosing callable." |
172 | | - } |
173 | | - |
174 | | - private DataFlowType typeRepr() { result = getNodeType(_) } |
175 | | - |
176 | | - query predicate compatibleTypesReflexive(DataFlowType t, string msg) { |
177 | | - t = typeRepr() and |
178 | | - not compatibleTypes(t, t) and |
179 | | - msg = "Type compatibility predicate is not reflexive." |
180 | | - } |
181 | | - |
182 | | - query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { |
183 | | - isUnreachableInCall(n, call) and |
184 | | - exists(DataFlowCallable c | |
185 | | - c = nodeGetEnclosingCallable(n) and |
186 | | - not viableCallable(call) = c |
187 | | - ) and |
188 | | - msg = "Call context for isUnreachableInCall is inconsistent with call graph." |
189 | | - } |
190 | | - |
191 | | - query predicate localCallNodes(DataFlowCall call, Node n, string msg) { |
192 | | - ( |
193 | | - n = getAnOutNode(call, _) and |
194 | | - msg = "OutNode and call does not share enclosing callable." |
195 | | - or |
196 | | - n.(ArgumentNode).argumentOf(call, _) and |
197 | | - msg = "ArgumentNode and call does not share enclosing callable." |
198 | | - ) and |
199 | | - nodeGetEnclosingCallable(n) != call.getEnclosingCallable() |
200 | | - } |
201 | | - |
202 | | - // This predicate helps the compiler forget that in some languages |
203 | | - // it is impossible for a result of `getPreUpdateNode` to be an |
204 | | - // instance of `PostUpdateNode`. |
205 | | - private Node getPre(PostUpdateNode n) { |
206 | | - result = n.getPreUpdateNode() |
| 6 | +private import cpp |
| 7 | +private import DataFlowImplSpecific |
| 8 | +private import TaintTrackingImplSpecific |
| 9 | +private import codeql.dataflow.internal.DataFlowImplConsistency |
| 10 | + |
| 11 | +private module Input implements InputSig<CppOldDataFlow> { |
| 12 | + predicate argHasPostUpdateExclude(Private::ArgumentNode n) { |
| 13 | + // Is the null pointer (or something that's not really a pointer) |
| 14 | + exists(n.asExpr().getValue()) |
207 | 15 | or |
208 | | - none() |
209 | | - } |
210 | | - |
211 | | - query predicate postIsNotPre(PostUpdateNode n, string msg) { |
212 | | - getPre(n) = n and |
213 | | - msg = "PostUpdateNode should not equal its pre-update node." |
214 | | - } |
215 | | - |
216 | | - query predicate postHasUniquePre(PostUpdateNode n, string msg) { |
217 | | - not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and |
218 | | - exists(int c | |
219 | | - c = count(n.getPreUpdateNode()) and |
220 | | - c != 1 and |
221 | | - msg = "PostUpdateNode should have one pre-update node but has " + c + "." |
| 16 | + // Isn't a pointer or is a pointer to const |
| 17 | + forall(DerivedType dt | dt = n.asExpr().getActualType() | |
| 18 | + dt.getBaseType().isConst() |
| 19 | + or |
| 20 | + dt.getBaseType() instanceof RoutineType |
222 | 21 | ) |
223 | | - } |
224 | | - |
225 | | - query predicate uniquePostUpdate(Node n, string msg) { |
226 | | - not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and |
227 | | - 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and |
228 | | - msg = "Node has multiple PostUpdateNodes." |
229 | | - } |
230 | | - |
231 | | - query predicate postIsInSameCallable(PostUpdateNode n, string msg) { |
232 | | - nodeGetEnclosingCallable(n) != nodeGetEnclosingCallable(n.getPreUpdateNode()) and |
233 | | - msg = "PostUpdateNode does not share callable with its pre-update node." |
234 | | - } |
235 | | - |
236 | | - private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } |
237 | | - |
238 | | - query predicate reverseRead(Node n, string msg) { |
239 | | - exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and |
240 | | - not any(ConsistencyConfiguration conf).reverseReadExclude(n) and |
241 | | - msg = "Origin of readStep is missing a PostUpdateNode." |
242 | | - } |
243 | | - |
244 | | - query predicate argHasPostUpdate(ArgumentNode n, string msg) { |
245 | | - not hasPost(n) and |
246 | | - not any(ConsistencyConfiguration c).argHasPostUpdateExclude(n) and |
247 | | - msg = "ArgumentNode is missing PostUpdateNode." |
248 | | - } |
249 | | - |
250 | | - // This predicate helps the compiler forget that in some languages |
251 | | - // it is impossible for a `PostUpdateNode` to be the target of |
252 | | - // `simpleLocalFlowStep`. |
253 | | - private predicate isPostUpdateNode(Node n) { n instanceof PostUpdateNode or none() } |
254 | | - |
255 | | - query predicate postWithInFlow(Node n, string msg) { |
256 | | - isPostUpdateNode(n) and |
257 | | - not clearsContent(n, _) and |
258 | | - simpleLocalFlowStep(_, n) and |
259 | | - not any(ConsistencyConfiguration c).postWithInFlowExclude(n) and |
260 | | - msg = "PostUpdateNode should not be the target of local flow." |
261 | | - } |
262 | | - |
263 | | - query predicate viableImplInCallContextTooLarge( |
264 | | - DataFlowCall call, DataFlowCall ctx, DataFlowCallable callable |
265 | | - ) { |
266 | | - callable = viableImplInCallContext(call, ctx) and |
267 | | - not callable = viableCallable(call) and |
268 | | - not any(ConsistencyConfiguration c).viableImplInCallContextTooLargeExclude(call, ctx, callable) |
269 | | - } |
270 | | - |
271 | | - query predicate uniqueParameterNodeAtPosition( |
272 | | - DataFlowCallable c, ParameterPosition pos, Node p, string msg |
273 | | - ) { |
274 | | - not any(ConsistencyConfiguration conf).uniqueParameterNodeAtPositionExclude(c, pos, p) and |
275 | | - isParameterNode(p, c, pos) and |
276 | | - not exists(unique(Node p0 | isParameterNode(p0, c, pos))) and |
277 | | - msg = "Parameters with overlapping positions." |
278 | | - } |
279 | | - |
280 | | - query predicate uniqueParameterNodePosition( |
281 | | - DataFlowCallable c, ParameterPosition pos, Node p, string msg |
282 | | - ) { |
283 | | - not any(ConsistencyConfiguration conf).uniqueParameterNodePositionExclude(c, pos, p) and |
284 | | - isParameterNode(p, c, pos) and |
285 | | - not exists(unique(ParameterPosition pos0 | isParameterNode(p, c, pos0))) and |
286 | | - msg = "Parameter node with multiple positions." |
287 | | - } |
288 | | - |
289 | | - query predicate uniqueContentApprox(Content c, string msg) { |
290 | | - not exists(unique(ContentApprox approx | approx = getContentApprox(c))) and |
291 | | - msg = "Non-unique content approximation." |
292 | | - } |
293 | | - |
294 | | - query predicate identityLocalStep(Node n, string msg) { |
295 | | - simpleLocalFlowStep(n, n) and |
296 | | - not any(ConsistencyConfiguration c).identityLocalStepExclude(n) and |
297 | | - msg = "Node steps to itself" |
| 22 | + // The above list of cases isn't exhaustive, but it narrows down the |
| 23 | + // consistency alerts enough that most of them are interesting. |
298 | 24 | } |
299 | 25 | } |
| 26 | + |
| 27 | +module Consistency = MakeConsistency<CppOldDataFlow, CppOldTaintTracking, Input>; |
0 commit comments