Skip to content

Commit 8ca6c57

Browse files
authored
Merge pull request github#3118 from MathiasVP/ir-flow-fields
C++: IR field flow
2 parents e974006 + ba0429c commit 8ca6c57

File tree

9 files changed

+249
-17
lines changed

9 files changed

+249
-17
lines changed

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,12 @@ private class ArrayContent extends Content, TArrayContent {
186186
* value of `node1`.
187187
*/
188188
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
189-
none() // stub implementation
189+
exists(FieldAddressInstruction fa, StoreInstruction store |
190+
node1.asInstruction() = store and
191+
store.getDestinationAddress() = fa and
192+
node2.asInstruction().(ChiInstruction).getPartial() = store and
193+
f.(FieldContent).getField() = fa.getField()
194+
)
190195
}
191196

192197
/**
@@ -195,7 +200,12 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
195200
* `node2`.
196201
*/
197202
predicate readStep(Node node1, Content f, Node node2) {
198-
none() // stub implementation
203+
exists(FieldAddressInstruction fa, LoadInstruction load |
204+
load.getSourceAddress() = fa and
205+
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
206+
fa.getField() = f.(FieldContent).getField() and
207+
load = node2.asInstruction()
208+
)
199209
}
200210

201211
/**

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

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,26 @@ class Node extends TIRDataFlowNode {
5555
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
5656

5757
/** Gets the parameter corresponding to this node, if any. */
58-
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
58+
Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() }
5959

6060
/**
6161
* Gets the variable corresponding to this node, if any. This can be used for
6262
* modelling flow in and out of global variables.
6363
*/
6464
Variable asVariable() { result = this.(VariableNode).getVariable() }
6565

66+
/**
67+
* Gets the expression that is partially defined by this node, if any.
68+
*
69+
* Partial definitions are created for field stores (`x.y = taint();` is a partial
70+
* definition of `x`), and for calls that may change the value of an object (so
71+
* `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is
72+
* a partial definition of `&x`).
73+
*/
74+
Expr asPartialDefinition() {
75+
result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression()
76+
}
77+
6678
/**
6779
* DEPRECATED: See UninitializedNode.
6880
*
@@ -96,6 +108,9 @@ class Node extends TIRDataFlowNode {
96108
string toString() { none() } // overridden by subclasses
97109
}
98110

111+
/**
112+
* An instruction, viewed as a node in a data flow graph.
113+
*/
99114
class InstructionNode extends Node, TInstructionNode {
100115
Instruction instr;
101116

@@ -143,26 +158,45 @@ class ExprNode extends InstructionNode {
143158
}
144159

145160
/**
146-
* The value of a parameter at function entry, viewed as a node in a data
147-
* flow graph.
161+
* A node representing a `Parameter`. This includes both explicit parameters such
162+
* as `x` in `f(x)` and implicit parameters such as `this` in `x.f()`
148163
*/
149164
class ParameterNode extends InstructionNode {
150-
override InitializeParameterInstruction instr;
165+
ParameterNode() {
166+
instr instanceof InitializeParameterInstruction
167+
or
168+
instr instanceof InitializeThisInstruction
169+
}
151170

152171
/**
153172
* Holds if this node is the parameter of `c` at the specified (zero-based)
154173
* position. The implicit `this` parameter is considered to have index `-1`.
155174
*/
156-
predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
175+
predicate isParameterOf(Function f, int i) { none() } // overriden by subclasses
176+
}
177+
178+
/**
179+
* The value of a parameter at function entry, viewed as a node in a data
180+
* flow graph.
181+
*/
182+
private class ExplicitParameterNode extends ParameterNode {
183+
override InitializeParameterInstruction instr;
157184

185+
override predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
186+
187+
/** Gets the parameter corresponding to this node. */
158188
Parameter getParameter() { result = instr.getParameter() }
159189

160190
override string toString() { result = instr.getParameter().toString() }
161191
}
162192

163-
private class ThisParameterNode extends InstructionNode {
193+
private class ThisParameterNode extends ParameterNode {
164194
override InitializeThisInstruction instr;
165195

196+
override predicate isParameterOf(Function f, int i) {
197+
i = -1 and instr.getEnclosingFunction() = f
198+
}
199+
166200
override string toString() { result = "this" }
167201
}
168202

@@ -204,6 +238,38 @@ abstract class PostUpdateNode extends InstructionNode {
204238
abstract Node getPreUpdateNode();
205239
}
206240

241+
/**
242+
* The base class for nodes that perform "partial definitions".
243+
*
244+
* In contrast to a normal "definition", which provides a new value for
245+
* something, a partial definition is an expression that may affect a
246+
* value, but does not necessarily replace it entirely. For example:
247+
* ```
248+
* x.y = 1; // a partial definition of the object `x`.
249+
* x.y.z = 1; // a partial definition of the object `x.y`.
250+
* x.setY(1); // a partial definition of the object `x`.
251+
* setY(&x); // a partial definition of the object `x`.
252+
* ```
253+
*/
254+
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
255+
256+
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257+
override ChiInstruction instr;
258+
259+
ExplicitFieldStoreQualifierNode() {
260+
not instr.isResultConflated() and
261+
exists(StoreInstruction store, FieldInstruction field |
262+
instr.getPartial() = store and field = store.getDestinationAddress()
263+
)
264+
}
265+
266+
// There might be multiple `ChiInstructions` that has a particular instruction as
267+
// the total operand - so this definition gives consistency errors in
268+
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
269+
// this consistency failure has.
270+
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
271+
}
272+
207273
/**
208274
* A node that represents the value of a variable after a function call that
209275
* may have changed the variable because it's passed by reference.
@@ -288,6 +354,10 @@ class VariableNode extends Node, TVariableNode {
288354
*/
289355
InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr }
290356

357+
/**
358+
* Gets the `Node` corresponding to a definition by reference of the variable
359+
* that is passed as `argument` of a call.
360+
*/
291361
DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
292362

293363
/**
@@ -305,7 +375,7 @@ ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
305375
/**
306376
* Gets the `Node` corresponding to the value of `p` at function entry.
307377
*/
308-
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
378+
ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p }
309379

310380
/** Gets the `VariableNode` corresponding to the variable `v`. */
311381
VariableNode variableNode(Variable v) { result.getVariable() = v }
@@ -360,6 +430,28 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
360430
// for now.
361431
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
362432
or
433+
// The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
434+
// First, we add flow from write side-effects to non-conflated chi instructions through their
435+
// partial operands. Consider the following example:
436+
// ```
437+
// void setX(Point* p, int new_x) {
438+
// p->x = new_x;
439+
// }
440+
// ...
441+
// setX(&p, taint());
442+
// ```
443+
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
444+
// `setX`, which will be melded into `p` through a chi instruction.
445+
iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and
446+
not iTo.isResultConflated()
447+
or
448+
// Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
449+
// This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
450+
exists(ChiInstruction chi | iFrom = chi |
451+
not chi.isResultConflated() and
452+
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi
453+
)
454+
or
363455
// Flow through modeled functions
364456
modelFlow(iFrom, iTo)
365457
}

cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ localCallNodes
3030
postIsNotPre
3131
postHasUniquePre
3232
uniquePostUpdate
33+
| ref.cpp:83:5:83:17 | Chi | Node has multiple PostUpdateNodes. |
34+
| ref.cpp:109:5:109:22 | Chi | Node has multiple PostUpdateNodes. |
3335
postIsInSameCallable
3436
reverseRead
3537
storeIsPostUpdate

cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@
3131
| ref.cpp:53:17:53:18 | ref.cpp:62:10:62:11 | AST only |
3232
| ref.cpp:53:21:53:22 | ref.cpp:65:10:65:11 | AST only |
3333
| ref.cpp:55:23:55:28 | ref.cpp:56:10:56:11 | AST only |
34-
| ref.cpp:94:15:94:20 | ref.cpp:129:13:129:15 | AST only |
35-
| ref.cpp:109:15:109:20 | ref.cpp:132:13:132:15 | AST only |
36-
| ref.cpp:122:23:122:28 | ref.cpp:123:13:123:15 | AST only |
37-
| ref.cpp:125:19:125:24 | ref.cpp:126:13:126:15 | AST only |
3834
| test.cpp:75:7:75:8 | test.cpp:76:8:76:9 | AST only |
3935
| test.cpp:83:7:83:8 | test.cpp:84:8:84:18 | AST only |
4036
| test.cpp:83:7:83:8 | test.cpp:86:8:86:9 | AST only |
@@ -45,9 +41,6 @@
4541
| test.cpp:359:13:359:18 | test.cpp:365:10:365:14 | AST only |
4642
| test.cpp:373:13:373:18 | test.cpp:369:10:369:14 | AST only |
4743
| test.cpp:373:13:373:18 | test.cpp:375:10:375:14 | AST only |
48-
| test.cpp:382:48:382:54 | test.cpp:385:8:385:10 | AST only |
49-
| test.cpp:388:53:388:59 | test.cpp:392:8:392:10 | AST only |
50-
| test.cpp:388:53:388:59 | test.cpp:394:10:394:12 | AST only |
5144
| test.cpp:399:7:399:9 | test.cpp:401:8:401:10 | AST only |
5245
| test.cpp:405:7:405:9 | test.cpp:408:8:408:10 | AST only |
5346
| test.cpp:416:7:416:11 | test.cpp:418:8:418:12 | AST only |

cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
| globals.cpp:12:10:12:24 | flowTestGlobal1 | globals.cpp:13:23:13:28 | call to source |
4040
| globals.cpp:19:10:19:24 | flowTestGlobal2 | globals.cpp:23:23:23:28 | call to source |
4141
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
42+
| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source |
43+
| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source |
44+
| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source |
45+
| ref.cpp:132:13:132:15 | val | ref.cpp:109:15:109:20 | call to source |
4246
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
4347
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
4448
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |
@@ -61,6 +65,9 @@
6165
| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source |
6266
| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source |
6367
| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source |
68+
| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 |
69+
| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 |
70+
| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 |
6471
| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 |
6572
| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 |
6673
| true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | call to source |
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
edges
2+
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
3+
| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] |
4+
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store |
5+
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
6+
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
7+
| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] |
8+
| A.cpp:154:13:154:13 | c | A.cpp:154:10:154:13 | (void *)... |
9+
| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
10+
| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] |
11+
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store |
12+
| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
13+
| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] |
14+
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store |
15+
| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 |
16+
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] |
17+
| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 |
18+
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:26:19:26:20 | Chi [m1] |
19+
| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 |
20+
| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 |
21+
| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] |
22+
| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] |
23+
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store |
24+
| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 |
25+
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 |
26+
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 |
27+
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 |
28+
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a |
29+
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
30+
nodes
31+
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
32+
| A.cpp:142:7:142:20 | Store | semmle.label | Store |
33+
| A.cpp:142:14:142:20 | new | semmle.label | new |
34+
| A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] |
35+
| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] |
36+
| A.cpp:154:10:154:13 | (void *)... | semmle.label | (void *)... |
37+
| A.cpp:154:13:154:13 | c | semmle.label | c |
38+
| A.cpp:154:13:154:13 | c | semmle.label | c |
39+
| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] |
40+
| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store |
41+
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
42+
| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] |
43+
| aliasing.cpp:13:3:13:21 | Store | semmle.label | Store |
44+
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
45+
| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] |
46+
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] |
47+
| aliasing.cpp:26:19:26:20 | Chi [m1] | semmle.label | Chi [m1] |
48+
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] |
49+
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
50+
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
51+
| aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input |
52+
| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 |
53+
| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input |
54+
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
55+
| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] |
56+
| aliasing.cpp:60:3:60:22 | Store | semmle.label | Store |
57+
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
58+
| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] |
59+
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
60+
| aliasing.cpp:79:11:79:20 | call to user_input | semmle.label | call to user_input |
61+
| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 |
62+
| aliasing.cpp:86:10:86:19 | call to user_input | semmle.label | call to user_input |
63+
| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 |
64+
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
65+
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
66+
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
67+
| struct_init.c:22:11:22:11 | a | semmle.label | a |
68+
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
69+
| struct_init.c:31:23:31:23 | a | semmle.label | a |
70+
#select
71+
| A.cpp:154:10:154:13 | (void *)... | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | (void *)... | (void *)... flows from $@ | A.cpp:142:14:142:20 | new | new |
72+
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
73+
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input |
74+
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input |
75+
| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input | call to user_input |
76+
| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input | call to user_input |
77+
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input |
78+
| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input | call to user_input |
79+
| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input | call to user_input |
80+
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input |
81+
| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
82+
| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* @kind path-problem
3+
*/
4+
5+
import semmle.code.cpp.ir.dataflow.DataFlow
6+
import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
7+
import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
8+
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl
9+
import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon
10+
import semmle.code.cpp.ir.IR
11+
import DataFlow::PathGraph
12+
import cpp
13+
14+
class Conf extends DataFlow::Configuration {
15+
Conf() { this = "FieldFlowConf" }
16+
17+
override predicate isSource(Node src) {
18+
src.asExpr() instanceof NewExpr
19+
or
20+
src.asExpr().(Call).getTarget().hasName("user_input")
21+
or
22+
exists(FunctionCall fc |
23+
fc.getAnArgument() = src.asDefiningArgument() and
24+
fc.getTarget().hasName("argument_source")
25+
)
26+
}
27+
28+
override predicate isSink(Node sink) {
29+
exists(Call c |
30+
c.getTarget().hasName("sink") and
31+
c.getAnArgument() = sink.asExpr()
32+
)
33+
}
34+
35+
override predicate isAdditionalFlowStep(Node a, Node b) {
36+
b.asPartialDefinition() =
37+
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
38+
.getQualifier()
39+
or
40+
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
41+
}
42+
}
43+
44+
from DataFlow::PathNode src, DataFlow::PathNode sink, Conf conf
45+
where conf.hasFlowPath(src, sink)
46+
select sink, src, sink, sink + " flows from $@", src, src.toString()

cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
| taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only |
2929
| taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only |
3030
| taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only |
31-
| taint.cpp:216:7:216:7 | taint.cpp:207:6:207:11 | AST only |
3231
| taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only |
3332
| taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only |
3433
| taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | AST only |

0 commit comments

Comments
 (0)