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 992e995094e..20bdf7afe45 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 @@ -44,11 +44,12 @@ private newtype TIRDataFlowNode = TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) { Ssa::isModifiableByCall(operand, indirectionIndex) } or - TRawIndirectOperand(Operand op, int indirectionIndex) { - Ssa::hasRawIndirectOperand(op, indirectionIndex) + TRawIndirectOperand0(Node0Impl node, int indirectionIndex) { + Ssa::hasRawIndirectOperand(node.asOperand(), indirectionIndex) } or - TRawIndirectInstruction(Instruction instr, int indirectionIndex) { - Ssa::hasRawIndirectInstruction(instr, indirectionIndex) + TRawIndirectInstruction0(Node0Impl node, int indirectionIndex) { + not exists(node.asOperand()) and + Ssa::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex) } or TFinalParameterNode(Parameter p, int indirectionIndex) { exists(Ssa::FinalParameterUse use | @@ -918,48 +919,146 @@ Type getTypeImpl(Type t, int indirectionIndex) { result instanceof UnknownType } -/** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an operand in the IR - * after `index` number of loads. - */ -class RawIndirectOperand extends Node, TRawIndirectOperand { - Operand operand; - int indirectionIndex; +private module RawIndirectNodes { + /** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an operand in the IR + * after `index` number of loads. + */ + private class RawIndirectOperand0 extends Node, TRawIndirectOperand0 { + Node0Impl node; + int indirectionIndex; - RawIndirectOperand() { this = TRawIndirectOperand(operand, indirectionIndex) } + RawIndirectOperand0() { this = TRawIndirectOperand0(node, indirectionIndex) } - /** Gets the underlying instruction. */ - Operand getOperand() { result = operand } + /** Gets the underlying instruction. */ + Operand getOperand() { result = node.asOperand() } - /** Gets the underlying indirection index. */ - int getIndirectionIndex() { result = indirectionIndex } + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } - override Declaration getFunction() { result = this.getOperand().getDef().getEnclosingFunction() } + override Declaration getFunction() { + result = this.getOperand().getDef().getEnclosingFunction() + } - override Declaration getEnclosingCallable() { result = this.getFunction() } + override Declaration getEnclosingCallable() { result = this.getFunction() } - override DataFlowType getType() { - exists(int sub, DataFlowType type, boolean isGLValue | - type = getOperandType(operand, isGLValue) and - if isGLValue = true then sub = 1 else sub = 0 - | - result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) - ) + override DataFlowType getType() { + exists(int sub, DataFlowType type, boolean isGLValue | + type = getOperandType(this.getOperand(), isGLValue) and + if isGLValue = true then sub = 1 else sub = 0 + | + result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) + ) + } + + final override Location getLocationImpl() { + if exists(this.getOperand().getLocation()) + then result = this.getOperand().getLocation() + else result instanceof UnknownDefaultLocation + } + + override string toStringImpl() { + result = operandNode(this.getOperand()).toStringImpl() + " indirection" + } } - final override Location getLocationImpl() { - if exists(this.getOperand().getLocation()) - then result = this.getOperand().getLocation() - else result instanceof UnknownDefaultLocation + /** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an instruction in the IR + * after `index` number of loads. + */ + private class RawIndirectInstruction0 extends Node, TRawIndirectInstruction0 { + Node0Impl node; + int indirectionIndex; + + RawIndirectInstruction0() { this = TRawIndirectInstruction0(node, indirectionIndex) } + + /** Gets the underlying instruction. */ + Instruction getInstruction() { result = node.asInstruction() } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override DataFlowType getType() { + exists(int sub, DataFlowType type, boolean isGLValue | + type = getInstructionType(this.getInstruction(), isGLValue) and + if isGLValue = true then sub = 1 else sub = 0 + | + result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) + ) + } + + final override Location getLocationImpl() { + if exists(this.getInstruction().getLocation()) + then result = this.getInstruction().getLocation() + else result instanceof UnknownDefaultLocation + } + + override string toStringImpl() { + result = instructionNode(this.getInstruction()).toStringImpl() + " indirection" + } } - override string toStringImpl() { - result = operandNode(this.getOperand()).toStringImpl() + " indirection" + /** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an operand in the IR + * after a number of loads. + */ + class RawIndirectOperand extends Node { + int indirectionIndex; + Operand operand; + + RawIndirectOperand() { + exists(Node0Impl node | operand = node.asOperand() | + this = TRawIndirectOperand0(node, indirectionIndex) + or + this = TRawIndirectInstruction0(node, indirectionIndex) + ) + } + + /** Gets the operand associated with this node. */ + Operand getOperand() { result = operand } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + } + + /** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an instruction in the IR + * after a number of loads. + */ + class RawIndirectInstruction extends Node { + int indirectionIndex; + Instruction instr; + + RawIndirectInstruction() { + exists(Node0Impl node | instr = node.asInstruction() | + this = TRawIndirectOperand0(node, indirectionIndex) + or + this = TRawIndirectInstruction0(node, indirectionIndex) + ) + } + + /** Gets the instruction associated with this node. */ + Instruction getInstruction() { result = instr } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } } } +import RawIndirectNodes + /** * INTERNAL: do not use. * @@ -1021,48 +1120,6 @@ class UninitializedNode extends Node { LocalVariable getLocalVariable() { result = v } } -/** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an instruction in the IR - * after `index` number of loads. - */ -class RawIndirectInstruction extends Node, TRawIndirectInstruction { - Instruction instr; - int indirectionIndex; - - RawIndirectInstruction() { this = TRawIndirectInstruction(instr, indirectionIndex) } - - /** Gets the underlying instruction. */ - Instruction getInstruction() { result = instr } - - /** Gets the underlying indirection index. */ - int getIndirectionIndex() { result = indirectionIndex } - - override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override DataFlowType getType() { - exists(int sub, DataFlowType type, boolean isGLValue | - type = getInstructionType(instr, isGLValue) and - if isGLValue = true then sub = 1 else sub = 0 - | - result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) - ) - } - - final override Location getLocationImpl() { - if exists(this.getInstruction().getLocation()) - then result = this.getInstruction().getLocation() - else result instanceof UnknownDefaultLocation - } - - override string toStringImpl() { - result = instructionNode(this.getInstruction()).toStringImpl() + " indirection" - } -} - private module GetConvertedResultExpression { private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag @@ -1600,26 +1657,29 @@ private module Cached { predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) } private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) { - // Reduce the indirection count by 1 if we're passing through a `LoadInstruction`. - exists(int ind, LoadInstruction load | - hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and - nodeHasInstruction(nodeTo, load, ind - 1) - ) - or - // If an operand flows to an instruction, then the indirection of - // the operand also flows to the indirection of the instruction. - exists(Operand operand, Instruction instr, int indirectionIndex | - simpleInstructionLocalFlowStep(operand, instr) and - hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and - hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex)) - ) - or - // If there's indirect flow to an operand, then there's also indirect - // flow to the operand after applying some pointer arithmetic. - exists(PointerArithmeticInstruction pointerArith, int indirectionIndex | - hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(), - pragma[only_bind_into](indirectionIndex)) and - hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex)) + nodeFrom != nodeTo and + ( + // Reduce the indirection count by 1 if we're passing through a `LoadInstruction`. + exists(int ind, LoadInstruction load | + hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and + nodeHasInstruction(nodeTo, load, ind - 1) + ) + or + // If an operand flows to an instruction, then the indirection of + // the operand also flows to the indirection of the instruction. + exists(Operand operand, Instruction instr, int indirectionIndex | + simpleInstructionLocalFlowStep(operand, instr) and + hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and + hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex)) + ) + or + // If there's indirect flow to an operand, then there's also indirect + // flow to the operand after applying some pointer arithmetic. + exists(PointerArithmeticInstruction pointerArith, int indirectionIndex | + hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(), + pragma[only_bind_into](indirectionIndex)) and + hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex)) + ) ) } @@ -1645,6 +1705,7 @@ private module Cached { private predicate indirectionInstructionFlow( RawIndirectInstruction nodeFrom, IndirectOperand nodeTo ) { + nodeFrom != nodeTo and // If there's flow from an instruction to an operand, then there's also flow from the // indirect instruction to the indirect operand. exists(Operand operand, Instruction instr, int indirectionIndex |