Skip to content

Commit b1c826e

Browse files
authored
Merge pull request #4135 from rdmarsh2/rdmarsh2/cpp/output-iterators-1
C++: Output iterators in AST taint tracking
2 parents 8d4f7e2 + 68f6d93 commit b1c826e

File tree

11 files changed

+603
-75
lines changed

11 files changed

+603
-75
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
private import cpp
22
private import DataFlowUtil
33
private import DataFlowDispatch
4+
private import FlowVar
45

56
/** Gets the instance argument of a non-static call. */
67
private Node getInstanceArgument(Call call) {
@@ -106,7 +107,7 @@ private class ExprOutNode extends OutNode, ExprNode {
106107
override DataFlowCall getCall() { result = this.getExpr() }
107108
}
108109

109-
private class RefOutNode extends OutNode, DefinitionByReferenceNode {
110+
private class RefOutNode extends OutNode, DefinitionByReferenceOrIteratorNode {
110111
/** Gets the underlying call. */
111112
override DataFlowCall getCall() { result = this.getArgument().getParent() }
112113
}
@@ -120,7 +121,7 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
120121
kind = TNormalReturnKind()
121122
or
122123
exists(int i |
123-
result.asDefiningArgument() = call.getArgument(i) and
124+
result.(DefinitionByReferenceOrIteratorNode).getArgument() = call.getArgument(i) and
124125
kind = TRefReturnKind(i)
125126
)
126127
}

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,28 +183,29 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode {
183183
}
184184

185185
/**
186-
* A node that represents the value of a variable after a function call that
187-
* may have changed the variable because it's passed by reference.
186+
* INTERNAL: do not use.
188187
*
189-
* A typical example would be a call `f(&x)`. Firstly, there will be flow into
190-
* `x` from previous definitions of `x`. Secondly, there will be a
191-
* `DefinitionByReferenceNode` to represent the value of `x` after the call has
192-
* returned. This node will have its `getArgument()` equal to `&x`.
188+
* A node that represents the value of a variable after a function call that
189+
* may have changed the variable because it's passed by reference or because an
190+
* iterator for it was passed by value or by reference.
193191
*/
194-
class DefinitionByReferenceNode extends PartialDefinitionNode {
192+
class DefinitionByReferenceOrIteratorNode extends PartialDefinitionNode {
195193
Expr inner;
196194
Expr argument;
197195

198-
DefinitionByReferenceNode() {
199-
this.getPartialDefinition().(DefinitionByReference).definesExpressions(inner, argument)
196+
DefinitionByReferenceOrIteratorNode() {
197+
this.getPartialDefinition().definesExpressions(inner, argument) and
198+
(
199+
this.getPartialDefinition() instanceof DefinitionByReference
200+
or
201+
this.getPartialDefinition() instanceof DefinitionByIterator
202+
)
200203
}
201204

202205
override Function getFunction() { result = inner.getEnclosingFunction() }
203206

204207
override Type getType() { result = inner.getType() }
205208

206-
override string toString() { result = "ref arg " + argument.toString() }
207-
208209
override Location getLocation() { result = argument.getLocation() }
209210

210211
override ExprNode getPreUpdateNode() { result.getExpr() = argument }
@@ -221,6 +222,21 @@ class DefinitionByReferenceNode extends PartialDefinitionNode {
221222
}
222223
}
223224

225+
/**
226+
* A node that represents the value of a variable after a function call that
227+
* may have changed the variable because it's passed by reference.
228+
*
229+
* A typical example would be a call `f(&x)`. Firstly, there will be flow into
230+
* `x` from previous definitions of `x`. Secondly, there will be a
231+
* `DefinitionByReferenceNode` to represent the value of `x` after the call has
232+
* returned. This node will have its `getArgument()` equal to `&x`.
233+
*/
234+
class DefinitionByReferenceNode extends DefinitionByReferenceOrIteratorNode {
235+
override VariablePartialDefinition pd;
236+
237+
override string toString() { result = "ref arg " + argument.toString() }
238+
}
239+
224240
/**
225241
* The value of an uninitialized local variable, viewed as a node in a data
226242
* flow graph.
@@ -284,20 +300,36 @@ abstract class PostUpdateNode extends Node {
284300
override Location getLocation() { result = getPreUpdateNode().getLocation() }
285301
}
286302

287-
private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
303+
abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
288304
PartialDefinition pd;
289305

290306
PartialDefinitionNode() { this = TPartialDefinitionNode(pd) }
291307

292-
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
293-
294308
override Location getLocation() { result = pd.getActualLocation() }
295309

296310
PartialDefinition getPartialDefinition() { result = pd }
297311

298312
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
299313
}
300314

315+
private class VariablePartialDefinitionNode extends PartialDefinitionNode {
316+
override VariablePartialDefinition pd;
317+
318+
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
319+
}
320+
321+
/**
322+
* INTERNAL: do not use.
323+
*
324+
* A synthetic data flow node used for flow into a collection when an iterator
325+
* write occurs in a callee.
326+
*/
327+
class IteratorPartialDefinitionNode extends PartialDefinitionNode {
328+
override IteratorPartialDefinition pd;
329+
330+
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
331+
}
332+
301333
/**
302334
* A post-update node on the `e->f` in `f(&e->f)` (and other forms).
303335
*/

0 commit comments

Comments
 (0)