Skip to content

Commit ae1a30e

Browse files
committed
C++: Add PostUpdateNode for updates to structs with no chi node
1 parent 243dea7 commit ae1a30e

2 files changed

Lines changed: 42 additions & 6 deletions

File tree

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,16 @@ private class ArrayContent extends Content, TArrayContent {
180180
override Type getType() { none() }
181181
}
182182

183-
/**
184-
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
185-
* Thus, `node2` references an object with a field `f` that contains the
186-
* value of `node1`.
187-
*/
188-
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
183+
private predicate storeStepNoChi(Node node1, Content f, PostUpdateNode node2) {
184+
exists(FieldAddressInstruction fa, StoreInstruction store |
185+
store = node2.asInstruction() and
186+
store.getDestinationAddress() = fa and
187+
store.getSourceValue() = node1.asInstruction() and
188+
f.(FieldContent).getField() = fa.getField()
189+
)
190+
}
191+
192+
private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
189193
exists(FieldAddressInstruction fa, StoreInstruction store |
190194
node1.asInstruction() = store and
191195
store.getDestinationAddress() = fa and
@@ -194,6 +198,16 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
194198
)
195199
}
196200

201+
/**
202+
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
203+
* Thus, `node2` references an object with a field `f` that contains the
204+
* value of `node1`.
205+
*/
206+
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
207+
storeStepNoChi(node1, f, node2) or
208+
storeStepChi(node1, f, node2)
209+
}
210+
197211
/**
198212
* Holds if data can flow from `node1` to `node2` via a read of `f`.
199213
* Thus, `node1` references an object with a field `f` whose value ends up in

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,19 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
270270
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
271271
}
272272

273+
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
274+
override StoreInstruction instr;
275+
276+
ExplicitSingleFieldStoreQualifierNode() {
277+
exists(FieldAddressInstruction field |
278+
field = instr.getDestinationAddress() and
279+
not exists(ChiInstruction chi | chi.getPartial() = instr)
280+
)
281+
}
282+
283+
override Node getPreUpdateNode() { none() }
284+
}
285+
273286
/**
274287
* A node that represents the value of a variable after a function call that
275288
* may have changed the variable because it's passed by reference.
@@ -404,6 +417,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
404417
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
405418
}
406419

420+
private predicate hasSize(Type t, int size) { t.getSize() = size }
421+
407422
cached
408423
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {
409424
iTo.(CopyInstruction).getSourceValue() = iFrom
@@ -452,6 +467,13 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
452467
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi
453468
)
454469
or
470+
iTo.(CopyInstruction).getSourceValueOperand().getAnyDef() = iFrom and
471+
exists(Class c, int size |
472+
c = iTo.getResultType() and
473+
hasSize(c, size) and
474+
hasSize(iFrom.getResultType(), size)
475+
)
476+
or
455477
// Flow through modeled functions
456478
modelFlow(iFrom, iTo)
457479
}

0 commit comments

Comments
 (0)