diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index db95fa94f9f1..8c6ec0b7612e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -1696,16 +1696,7 @@ private module Cached { // Reverse flow: data that flows from the definition node back into the indirection returned // by a function. This allows data to flow 'in' through references returned by a modeled // function such as `operator[]`. - exists(Operand address, int indirectionIndex | - nodeHasOperand(nodeTo.(IndirectReturnOutNode), address, indirectionIndex) - | - exists(StoreInstruction store | - nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and - store.getDestinationAddressOperand() = address - ) - or - Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex) - ) + reverseFlow(nodeFrom, nodeTo) } private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) { @@ -1736,6 +1727,39 @@ private module Cached { ) ) } + + private predicate reverseFlow(Node nodeFrom, Node nodeTo) { + reverseFlowOperand(nodeFrom, nodeTo) + or + reverseFlowInstruction(nodeFrom, nodeTo) + } + + private predicate reverseFlowOperand(Node nodeFrom, IndirectReturnOutNode nodeTo) { + exists(Operand address, int indirectionIndex | + nodeHasOperand(nodeTo, address, indirectionIndex) + | + exists(StoreInstruction store | + nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and + store.getDestinationAddressOperand() = address + ) + or + // We also want a write coming out of an `OutNode` to flow `nodeTo`. + // This is different from `reverseFlowInstruction` since `nodeFrom` can never + // be an `OutNode` when it's defined by an instruction. + Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex) + ) + } + + private predicate reverseFlowInstruction(Node nodeFrom, IndirectReturnOutNode nodeTo) { + exists(Instruction address, int indirectionIndex | + nodeHasInstruction(nodeTo, address, indirectionIndex) + | + exists(StoreInstruction store | + nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and + store.getDestinationAddress() = address + ) + ) + } } import Cached