C++: Add ReadSideEffect as a possible end instruction for load chains

This commit is contained in:
Mathias Vorreiter Pedersen
2020-06-08 11:05:30 +02:00
parent a4388e9258
commit 01f3793159
2 changed files with 28 additions and 14 deletions

View File

@@ -611,19 +611,7 @@ private newtype TLoadChain =
)
}
/**
* This class abstracts out the information needed to end a `LoadChain`. For now the only
* implementation is `LoadChainEndInstructionLoad`, but we may need another implementation similar
* to `StoreChainEndInstructionSideEffect` to handle cases like:
* ```
* void read_f(Inner* inner) {
* sink(inner->f);
* }
* ...
* outer.inner.f = taint();
* read_f(&outer.inner);
* ```
*/
/** This class abstracts out the information needed to end a `LoadChain`. */
abstract private class LoadChainEndInstruction extends Instruction {
abstract FieldAddressInstruction getFieldInstruction();
@@ -643,6 +631,32 @@ private class LoadChainEndInstructionLoad extends LoadChainEndInstruction, LoadI
override Instruction getReadValue() { result = getSourceValueOperand().getAnyDef() }
}
/**
* Ends a `LoadChain` with a `ReadSideEffectInstruction`. This ensures that we pop content from the
* access path when passing an argument that reads a field. For example in:
* ```
* void read_f(Inner* inner) {
* sink(inner->f);
* }
* ...
* outer.inner.f = taint();
* read_f(&outer.inner);
* ```
* In order to register `inner->f` as a `readStep`, the head of the access path must
* be `f`, and thus reading `&outer.inner` must pop `inner` from the access path
* before entering `read_f`.
*/
private class LoadChainInstructionSideEffect extends LoadChainEndInstruction,
ReadSideEffectInstruction {
FieldAddressInstruction fi;
LoadChainInstructionSideEffect() { fi = skipConversion*(this.getArgumentDef()) }
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Instruction getReadValue() { result = getSideEffectOperand().getAnyDef() }
}
/**
* A `LoadChain` represents a series of field lookups that compute the source address of a load.
* For example, given the field lookup in `f(a.b.c)`, there are two `LoadChains`s:

View File

@@ -158,7 +158,7 @@ struct Outer
void read_f(Inner *inner)
{
sink(inner->f); //$ast $f-:ir
sink(inner->f); //$ast,ir
}
void test()