Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 077c282

Browse files
committed
C++: Add field flow and accept tests
1 parent a5f08e1 commit 077c282

3 files changed

Lines changed: 128 additions & 15 deletions

File tree

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,14 @@ private class ArrayContent extends Content, TArrayContent {
131131
* value of `node1`.
132132
*/
133133
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
134-
none() // stub implementation
134+
exists(FieldAddressInstruction fa |
135+
exists(StoreInstruction store |
136+
node1.asInstruction() = store and
137+
store.getDestinationAddress() = fa
138+
) and
139+
node2.getPreUpdateNode().asInstruction() = fa.getObjectAddress() and
140+
f.(FieldContent).getField() = fa.getField()
141+
)
135142
}
136143

137144
/**
@@ -140,7 +147,12 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
140147
* `node2`.
141148
*/
142149
predicate readStep(Node node1, Content f, Node node2) {
143-
none() // stub implementation
150+
exists(FieldAddressInstruction fa, LoadInstruction load |
151+
load.getSourceAddress() = fa and
152+
node1.asInstruction() = fa.getObjectAddress() and
153+
fa.getField() = f.(FieldContent).getField() and
154+
load = node2.asInstruction()
155+
)
144156
}
145157

146158
/**

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

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class Node extends TIRDataFlowNode {
6363
*/
6464
Variable asVariable() { result = this.(VariableNode).getVariable() }
6565

66+
Expr asPartialDefinition() {
67+
result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression()
68+
}
6669

6770
/**
6871
* DEPRECATED: See UninitializedNode.
@@ -213,6 +216,19 @@ abstract class PostUpdateNode extends InstructionNode {
213216
* Gets the node before the state update.
214217
*/
215218
abstract Node getPreUpdateNode();
219+
220+
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
221+
}
222+
223+
abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
224+
225+
class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
226+
override StoreInstruction instr;
227+
FieldAddressInstruction field;
228+
229+
ExplicitFieldStoreQualifierNode() { field = instr.getDestinationAddress() }
230+
231+
override Node getPreUpdateNode() { result.asInstruction() = field.getObjectAddress() }
216232
}
217233

218234
/**
@@ -225,31 +241,49 @@ abstract class PostUpdateNode extends InstructionNode {
225241
* returned. This node will have its `getArgument()` equal to `&x` and its
226242
* `getVariableAccess()` equal to `x`.
227243
*/
228-
class DefinitionByReferenceNode extends InstructionNode {
244+
class DefinitionByReferenceNode extends PartialDefinitionNode {
229245
override WriteSideEffectInstruction instr;
246+
CallInstruction call;
247+
248+
DefinitionByReferenceNode() { call = instr.getPrimaryInstruction() }
249+
250+
override Node getPreUpdateNode() {
251+
result.asInstruction() = call.getPositionalArgument(instr.getIndex())
252+
or
253+
result.asInstruction() = call.getThisArgument() and
254+
instr.getIndex() = -1
255+
}
230256

231257
/** Gets the argument corresponding to this node. */
232258
Expr getArgument() {
233-
result =
234-
instr
235-
.getPrimaryInstruction()
236-
.(CallInstruction)
237-
.getPositionalArgument(instr.getIndex())
238-
.getUnconvertedResultExpression()
259+
result = call.getPositionalArgument(instr.getIndex()).getUnconvertedResultExpression()
239260
or
240-
result =
241-
instr
242-
.getPrimaryInstruction()
243-
.(CallInstruction)
244-
.getThisArgument()
245-
.getUnconvertedResultExpression() and
261+
result = call.getThisArgument().getUnconvertedResultExpression() and
246262
instr.getIndex() = -1
247263
}
248264

249265
/** Gets the parameter through which this value is assigned. */
250266
Parameter getParameter() {
251267
exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex()))
252268
}
269+
270+
override string toString() { result = "ref arg " + getPreUpdateNode().toString() }
271+
}
272+
273+
class PositionalArgumentWithoutWriteSideEffectNode extends PartialDefinitionNode {
274+
override CallInstruction instr;
275+
PositionalArgumentOperand op;
276+
277+
PositionalArgumentWithoutWriteSideEffectNode() {
278+
instr.getAnOperand() = op and
279+
not exists(WriteSideEffectInstruction write |
280+
write.getIndex() = op.getIndex() and write.getPrimaryInstruction() = instr
281+
)
282+
}
283+
284+
override Node getPreUpdateNode() { result.asInstruction() = op.getDef() }
285+
286+
override string toString() { result = "no change to " + op.toString() }
253287
}
254288

255289
/**
@@ -332,6 +366,13 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
332366
*/
333367
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
334368
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
369+
or
370+
exists(ChiInstruction chi, LoadInstruction load |
371+
chi.getPartial() = nodeFrom.(PartialDefinitionNode).getInstruction() and
372+
// TODO: This can probably be getSourceValue() after #3112 is merged
373+
load.getSourceValueOperand().getAnyDef() = chi and
374+
nodeTo.asInstruction() = load.getSourceAddress().(FieldAddressInstruction).getObjectAddress()
375+
)
335376
}
336377

337378
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {

cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,87 @@
11
edges
2+
| A.cpp:126:5:126:5 | ref arg b [c] : void | A.cpp:131:8:131:8 | ref arg b [c] : void |
3+
| A.cpp:126:12:126:18 | new : void | A.cpp:126:5:126:5 | ref arg b [c] : void |
4+
| A.cpp:131:8:131:8 | ref arg b [c] : void | A.cpp:132:10:132:10 | b [c] : void |
5+
| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c |
6+
| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c : void |
7+
| A.cpp:132:13:132:13 | c : void | A.cpp:132:10:132:13 | (void *)... |
8+
| aliasing.cpp:9:3:9:22 | s [post update] : void | aliasing.cpp:9:3:9:22 | s [post update] [m1] : void |
9+
| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void |
10+
| aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:9:3:9:22 | s [post update] : void |
11+
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void |
12+
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void |
13+
| aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void |
14+
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | aliasing.cpp:29:8:29:9 | s1 [m1] : void |
15+
| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | aliasing.cpp:30:8:30:9 | s2 [m1] : void |
16+
| aliasing.cpp:29:8:29:9 | s1 [m1] : void | aliasing.cpp:29:11:29:12 | m1 |
17+
| aliasing.cpp:30:8:30:9 | s2 [m1] : void | aliasing.cpp:30:11:30:12 | m1 |
18+
| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:38:11:38:12 | m1 |
19+
| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void |
220
| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 |
21+
| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:43:13:43:14 | m1 |
22+
| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | s2 [post update] : void |
323
| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 |
24+
| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:80:12:80:13 | m1 |
25+
| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | s [post update] : void |
426
| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 |
27+
| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:87:12:87:13 | m1 |
28+
| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void |
529
| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 |
30+
| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:93:12:93:13 | m1 |
31+
| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | s [post update] : void |
632
| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 |
33+
| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:22:11:22:11 | a |
34+
| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | VariableAddress [post update] : void |
735
| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a |
36+
| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:31:23:31:23 | a |
37+
| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | FieldAddress [post update] : void |
838
| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a |
939
nodes
40+
| A.cpp:126:5:126:5 | ref arg b [c] : void | semmle.label | ref arg b [c] : void |
41+
| A.cpp:126:12:126:18 | new : void | semmle.label | new : void |
42+
| A.cpp:131:8:131:8 | ref arg b [c] : void | semmle.label | ref arg b [c] : void |
43+
| A.cpp:132:10:132:10 | b [c] : void | semmle.label | b [c] : void |
44+
| A.cpp:132:10:132:13 | (void *)... | semmle.label | (void *)... |
45+
| A.cpp:132:13:132:13 | c | semmle.label | c |
46+
| A.cpp:132:13:132:13 | c : void | semmle.label | c : void |
47+
| aliasing.cpp:9:3:9:22 | s [post update] : void | semmle.label | s [post update] : void |
48+
| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void |
49+
| aliasing.cpp:9:11:9:20 | call to user_input : void | semmle.label | call to user_input : void |
50+
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void |
51+
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void |
52+
| aliasing.cpp:13:10:13:19 | call to user_input : void | semmle.label | call to user_input : void |
53+
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | semmle.label | ref arg & ... [m1] : void |
54+
| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | semmle.label | ref arg (reference to) [m1] : void |
55+
| aliasing.cpp:29:8:29:9 | s1 [m1] : void | semmle.label | s1 [m1] : void |
56+
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
57+
| aliasing.cpp:30:8:30:9 | s2 [m1] : void | semmle.label | s2 [m1] : void |
58+
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
59+
| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void |
1060
| aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void |
1161
| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 |
62+
| aliasing.cpp:42:3:42:22 | s2 [post update] : void | semmle.label | s2 [post update] : void |
1263
| aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void |
1364
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
65+
| aliasing.cpp:79:3:79:22 | s [post update] : void | semmle.label | s [post update] : void |
1466
| aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void |
1567
| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 |
68+
| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void |
1669
| aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void |
1770
| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 |
71+
| aliasing.cpp:92:3:92:23 | s [post update] : void | semmle.label | s [post update] : void |
1872
| aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void |
1973
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
74+
| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | semmle.label | VariableAddress [post update] : void |
2075
| struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void |
2176
| struct_init.c:22:11:22:11 | a | semmle.label | a |
77+
| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | semmle.label | FieldAddress [post update] : void |
2278
| struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void |
2379
| struct_init.c:31:23:31:23 | a | semmle.label | a |
2480
#select
81+
| A.cpp:132:10:132:13 | (void *)... | A.cpp:126:12:126:18 | new : void | A.cpp:132:10:132:13 | (void *)... | (void *)... flows from $@ | A.cpp:126:12:126:18 | new : void | new : void |
82+
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new : void | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new : void | new : void |
83+
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input : void | call to user_input : void |
84+
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input : void | call to user_input : void |
2585
| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void |
2686
| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input : void | call to user_input : void |
2787
| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input : void | call to user_input : void |

0 commit comments

Comments
 (0)