Skip to content

Commit 5719967

Browse files
committed
C++: Remove single-field case from PostUpdateNode and accept tests
1 parent c577541 commit 5719967

5 files changed

Lines changed: 33 additions & 41 deletions

File tree

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,10 @@ private class ArrayContent extends Content, TArrayContent {
131131
* value of `node1`.
132132
*/
133133
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
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
134+
exists(FieldAddressInstruction fa, StoreInstruction store |
135+
node1.asInstruction() = store and
136+
store.getDestinationAddress() = fa and
137+
node2.asInstruction().(ChiInstruction).getPartial() = store and
140138
f.(FieldContent).getField() = fa.getField()
141139
)
142140
}

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

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -264,22 +264,6 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
264264
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
265265
}
266266

267-
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
268-
override StoreInstruction instr;
269-
FieldAddressInstruction field;
270-
271-
ExplicitSingleFieldStoreQualifierNode() {
272-
field = instr.getDestinationAddress() and
273-
not exists(ChiInstruction chi | chi.getPartial() = instr)
274-
}
275-
276-
// Since there is no Chi instruction with a total operand for us to use we let the pre update node
277-
// be the address of the object containing the field.
278-
// Note that, unlike in the case where a struct has multiple fields (and thus has a `Chi`
279-
// instruction), the pre update node will be an instruction with a register result.
280-
override Node getPreUpdateNode() { result.asInstruction() = field.getObjectAddress() }
281-
}
282-
283267
/**
284268
* A node that represents the value of a variable after a function call that
285269
* may have changed the variable because it's passed by reference.
@@ -290,31 +274,31 @@ private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNod
290274
* returned. This node will have its `getArgument()` equal to `&x` and its
291275
* `getVariableAccess()` equal to `x`.
292276
*/
293-
class DefinitionByReferenceNode extends PartialDefinitionNode {
294-
override ChiInstruction instr;
295-
WriteSideEffectInstruction write;
296-
CallInstruction call;
297-
298-
DefinitionByReferenceNode() {
299-
not instr.isResultConflated() and
300-
instr.getPartial() = write and
301-
call = write.getPrimaryInstruction()
302-
}
303-
304-
// See the comment on ExplicitFieldStoreQualifierNode::getPreUpdateNode for comments on why
305-
// this causes failures in DataFlowImplConsistency::Consistency.
306-
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
277+
class DefinitionByReferenceNode extends InstructionNode {
278+
override WriteSideEffectInstruction instr;
307279

308280
/** Gets the argument corresponding to this node. */
309281
Expr getArgument() {
310-
result = call.getPositionalArgument(write.getIndex()).getUnconvertedResultExpression()
282+
result =
283+
instr
284+
.getPrimaryInstruction()
285+
.(CallInstruction)
286+
.getPositionalArgument(instr.getIndex())
287+
.getUnconvertedResultExpression()
311288
or
312-
result = call.getThisArgument().getUnconvertedResultExpression() and
313-
write.getIndex() = -1
289+
result =
290+
instr
291+
.getPrimaryInstruction()
292+
.(CallInstruction)
293+
.getThisArgument()
294+
.getUnconvertedResultExpression() and
295+
instr.getIndex() = -1
314296
}
315297

316298
/** Gets the parameter through which this value is assigned. */
317-
Parameter getParameter() { result = call.getStaticCallTarget().getParameter(write.getIndex()) }
299+
Parameter getParameter() {
300+
exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex()))
301+
}
318302
}
319303

320304
/**

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ postIsNotPre
3131
postHasUniquePre
3232
uniquePostUpdate
3333
| ref.cpp:83:5:83:17 | Chi | Node has multiple PostUpdateNodes. |
34-
| ref.cpp:100:34:100:36 | InitializeIndirection | Node has multiple PostUpdateNodes. |
3534
| ref.cpp:109:5:109:22 | Chi | Node has multiple PostUpdateNodes. |
3635
postIsInSameCallable
3736
reverseRead

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ edges
55
| aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:43:13:43:14 | m1 |
66
| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | Store : void |
77
| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 |
8+
| aliasing.cpp:60:3:60:22 | Chi [m1] : void | aliasing.cpp:61:13:61:14 | Store [m1] : void |
9+
| aliasing.cpp:60:3:60:22 | Store : void | aliasing.cpp:60:3:60:22 | Chi [m1] : void |
10+
| aliasing.cpp:60:11:60:20 | call to user_input : void | aliasing.cpp:60:3:60:22 | Store : void |
11+
| aliasing.cpp:61:13:61:14 | Store [m1] : void | aliasing.cpp:62:14:62:15 | m1 |
812
| aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:80:12:80:13 | m1 |
913
| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | Store : void |
1014
| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 |
@@ -27,6 +31,11 @@ nodes
2731
| aliasing.cpp:42:3:42:22 | Store : void | semmle.label | Store : void |
2832
| aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void |
2933
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
34+
| aliasing.cpp:60:3:60:22 | Chi [m1] : void | semmle.label | Chi [m1] : void |
35+
| aliasing.cpp:60:3:60:22 | Store : void | semmle.label | Store : void |
36+
| aliasing.cpp:60:11:60:20 | call to user_input : void | semmle.label | call to user_input : void |
37+
| aliasing.cpp:61:13:61:14 | Store [m1] : void | semmle.label | Store [m1] : void |
38+
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
3039
| aliasing.cpp:79:3:79:22 | Store : void | semmle.label | Store : void |
3140
| aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void |
3241
| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 |
@@ -45,6 +54,7 @@ nodes
4554
#select
4655
| 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 |
4756
| 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 |
57+
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input : void | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input : void | call to user_input : void |
4858
| 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 |
4959
| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input : void | call to user_input : void |
5060
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input : void | call to user_input : void |

cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
| funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets |
66
| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets |
77
| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets |
8+
| funcsLocal.c:58:9:58:10 | e1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread |

0 commit comments

Comments
 (0)