C++: Implement field flow for operator[] writes and pointer deref writes.

This commit is contained in:
Mathias Vorreiter Pedersen
2020-09-08 14:35:09 +02:00
parent 3a7bf2a15a
commit faae2e782a
3 changed files with 75 additions and 16 deletions

View File

@@ -264,9 +264,6 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
t instanceof Union
or
t instanceof ArrayType
or
// Buffers of unknown size
t instanceof UnknownType
)
or
exists(BinaryInstruction bin |

View File

@@ -181,24 +181,41 @@ private class CollectionContent extends Content, TCollectionContent {
}
private class ArrayContent extends Content, TArrayContent {
override string toString() { result = "array" }
ArrayContent() { this = TArrayContent() }
override string toString() { result = "array content" }
}
private predicate storeStepNoChi(Node node1, Content f, PostUpdateNode node2) {
private predicate fieldStoreStepNoChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(FieldAddressInstruction fa, StoreInstruction store |
store = node2.asInstruction() and
store.getDestinationAddress() = fa and
store.getSourceValue() = node1.asInstruction() and
f.(FieldContent).getField() = fa.getField()
f.getField() = fa.getField()
)
}
private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(FieldAddressInstruction fa, StoreInstruction store |
node1.asInstruction() = store and
store.getDestinationAddress() = fa and
node2.asInstruction().(ChiInstruction).getPartial() = store and
f.(FieldContent).getField() = fa.getField()
f.getField() = fa.getField()
)
}
private predicate arrayStoreStepChi(Node node1, Content a, PostUpdateNode node2) {
a instanceof ArrayContent and
exists(StoreInstruction store |
node1.asInstruction() = store and
(
// `x[i] = taint()`
store.getDestinationAddress() instanceof PointerAddInstruction
or
// `*p = taint()`
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
) and
node2.asInstruction().(ChiInstruction).getPartial() = store
)
}
@@ -208,8 +225,26 @@ private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
* value of `node1`.
*/
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
storeStepNoChi(node1, f, node2) or
storeStepChi(node1, f, node2)
fieldStoreStepNoChi(node1, f, node2) or
fieldStoreStepChi(node1, f, node2) or
arrayStoreStepChi(node1, f, node2)
}
private predicate fieldReadStep(Node node1, FieldContent f, Node node2) {
exists(FieldAddressInstruction fa, LoadInstruction load |
load.getSourceAddress() = fa and
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
fa.getField() = f.(FieldContent).getField() and
load = node2.asInstruction()
)
}
private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
exists(LoadInstruction load |
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
load = node2.asInstruction()
)
}
/**
@@ -218,12 +253,8 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
* `node2`.
*/
predicate readStep(Node node1, Content f, Node node2) {
exists(FieldAddressInstruction fa, LoadInstruction load |
load.getSourceAddress() = fa and
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
fa.getField() = f.(FieldContent).getField() and
load = node2.asInstruction()
)
fieldReadStep(node1, f, node2) or
arrayReadStep(node1, f, node2)
}
/**

View File

@@ -377,6 +377,37 @@ private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNod
}
}
private class ArrayStoreNode extends PartialDefinitionNode {
override ChiInstruction instr;
PointerAddInstruction add;
ArrayStoreNode() {
not instr.isResultConflated() and
exists(StoreInstruction store |
instr.getPartial() = store and
add = store.getDestinationAddress()
)
}
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
override Expr getDefinedExpr() { result = add.getLeft().getUnconvertedResultExpression() }
}
private class PointerStoreNode extends PostUpdateNode {
override ChiInstruction instr;
PointerStoreNode() {
not instr.isResultConflated() and
exists(StoreInstruction store |
instr.getPartial() = store and
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
)
}
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
}
/**
* A node that represents the value of a variable after a function call that
* may have changed the variable because it's passed by reference.