From ce34d91a0761c6cfe1a02788dc269143585d65b8 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 2 Jun 2020 13:50:00 +0200 Subject: [PATCH] C++: Add more QLDoc to StoreNode and LoadNode classes, and related predicates. I also simplified the code a bit by moving common implementations of predicates into shared super classes. Finally, I added a getLocation predicate to StoreNode to match the structure of the LoadNode class. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 69 ++++++++++++++++--- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index a025c325338..1a0e5969a45 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -462,20 +462,46 @@ private newtype TStoreChain = ) } +/** + * A `StoreChain` represents a series of field lookups that compute the destination of a store. + * For example, given an assignment such as `a.b.c = x`, there are two `StoreChain`s: + * One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent + * `StoreChain` of `c`. + */ private class StoreChain extends TStoreChain { string toString() { none() } - StoreChainConsCons getParent() { none() } + /** + * Gets the parent of this `StoreChain`, if any. For example, for the assignment + * ``` + * a.b.c = x; + * ``` + * the parent of `c` is `b`, and `b` has no parent. + */ + final StoreChainConsCons getParent() { result.getChild() = this } + /** Gets the child of this `StoreChain`, if any. */ StoreChain getChild() { none() } + /** + * Gets the instruction that receives flow from the outermost `StoreChain` of this chain (i.e., + * the `StoreChain` with no parent). + */ StoreChainEndInstruction getEndInstruction() { none() } + /** + * Gets the instruction that flows to the innermost `StoreChain` of this chain (i.e., + * the `StoreChain` with no child). + */ Instruction getBeginInstruction() { none() } + /** Gets the `FieldAddressInstruction` of this `StoreChain` */ FieldAddressInstruction getFieldInstruction() { none() } + /** Gets the `FieldAddressInstruction` of any `StoreChain` in this chain. */ FieldAddressInstruction getAFieldInstruction() { none() } + + final Location getLocation() { result = getFieldInstruction().getLocation() } } private class StoreChainConsNil extends StoreChain, TStoreChainConsNil { @@ -486,8 +512,6 @@ private class StoreChainConsNil extends StoreChain, TStoreChainConsNil { override string toString() { result = fi.getField().toString() } - override StoreChainConsCons getParent() { result = TStoreChainConsCons(_, this) } - override StoreChainEndInstruction getEndInstruction() { result = end } override Instruction getBeginInstruction() { result = end.getBeginInstruction() } @@ -505,8 +529,6 @@ private class StoreChainConsCons extends StoreChain, TStoreChainConsCons { override string toString() { result = fi.getField().toString() + "." + next.toString() } - override StoreChainConsCons getParent() { result.getChild() = this } - override StoreChain getChild() { result = next } override FieldAddressInstruction getFieldInstruction() { result = fi } @@ -563,18 +585,34 @@ private class LoadChainEndInstructionLoad extends LoadChainEndInstruction, LoadI override Instruction getReadValue() { result = getSourceValueOperand().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: + * One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent + * `LoadChain` of `c`. + */ private class LoadChain extends TLoadChain { string toString() { none() } + /** + * Gets the instruction that receives flow from the innermost `LoadChain` of this chain (i.e., + * the `LoadChain` with no child). + */ LoadChainEndInstruction getEndInstruction() { none() } + /** + * Gets the parent of this `LoadChain`, if any. For example in `f(a.b.c)` the parent of `c` is `b`, + * and `b` has no parent. + */ final LoadChainConsCons getParent() { result.getChild() = this } + /** Gets the child of this `LoadChain`, if any. */ LoadChain getChild() { none() } + /** Gets the `FieldAddressInstruction` of this `LoadChain` */ FieldAddressInstruction getFieldInstruction() { none() } - Location getLocation() { none() } + final Location getLocation() { result = getFieldInstruction().getLocation() } } private class LoadChainConsNil extends LoadChain, TLoadChainConsNil { @@ -588,8 +626,6 @@ private class LoadChainConsNil extends LoadChain, TLoadChainConsNil { override LoadChainEndInstruction getEndInstruction() { result = end } override FieldAddressInstruction getFieldInstruction() { result = fi } - - override Location getLocation() { result = fi.getLocation() } } private class LoadChainConsCons extends LoadChain, TLoadChainConsCons { @@ -605,11 +641,21 @@ private class LoadChainConsCons extends LoadChain, TLoadChainConsCons { override LoadChain getChild() { result = next } override FieldAddressInstruction getFieldInstruction() { result = fi } - - override Location getLocation() { result = fi.getLocation() } } -/** `StoreNode` also extends `ReadStepNode` to participate in reverse read steps. */ +/** + * A dataflow node generated by a partial definition. + * The `StoreNode` class extends `ReadStepNode` to participate in reverse read steps. + * A reverse read is a store step that is "inferred" by the DataFlow library. For example in the + * assignment: + * ``` + * a.b.c = x; + * ``` + * Here, the access path after the store must reflect that a value has been stored into the field `c` of + * the object at field `b`. The field `c` is added to the access path through a `storeStep`, and the + * field `b` is inferred by the DataFlow library because there's a read step (reading the field `b`) from + * the pre update node for `b.c` to the pre update node for `c`. + */ private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, PartialDefinitionNode { StoreChain storeChain; @@ -649,6 +695,7 @@ private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, Partial } } +/** A dataflow node generated by loading from an address computed by a sequence of fields lookups. */ private class LoadNode extends TLoadNode, ReadStepNode { LoadChain loadChain;