diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll index 49b8009828b..4e9a90dc0a1 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll @@ -94,8 +94,9 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) { cached private newtype TDefOrUseImpl = - TDefImpl(Operand address, int indirectionIndex) { - exists(Instruction base | isDef(_, _, address, base, _, indirectionIndex) | + TDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) { + isDef(_, _, address, base, _, indirectionIndex) and + ( // We only include the definition if the SSA pruning stage // concluded that the definition is live after the write. any(SsaInternals0::Def def).getAddressOperand() = address @@ -105,8 +106,8 @@ private newtype TDefOrUseImpl = base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable ) } or - TUseImpl(Operand operand, int indirectionIndex) { - isUse(_, operand, _, _, indirectionIndex) and + TUseImpl(BaseSourceVariableInstruction base, Operand operand, int indirectionIndex) { + isUse(_, operand, base, _, indirectionIndex) and not isDef(_, _, operand, _, _, _) } or TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) { @@ -193,7 +194,7 @@ abstract private class DefOrUseImpl extends TDefOrUseImpl { /** * Gets the instruction that computes the base of this definition or use. - * This is always a `VariableAddressInstruction` or an `AllocationInstruction`. + * This is always a `VariableAddressInstruction` or an `CallInstruction`. */ abstract BaseSourceVariableInstruction getBase(); @@ -265,15 +266,17 @@ abstract class DefImpl extends DefOrUseImpl { } private class DirectDef extends DefImpl, TDefImpl { - DirectDef() { this = TDefImpl(address, ind) } + BaseSourceVariableInstruction base; - override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) } + DirectDef() { this = TDefImpl(base, address, ind) } - override int getIndirection() { isDef(_, _, address, _, result, ind) } + override BaseSourceVariableInstruction getBase() { result = base } - override Node0Impl getValue() { isDef(_, result, address, _, _, _) } + override int getIndirection() { isDef(_, _, address, base, result, ind) } - override predicate isCertain() { isDef(true, _, address, _, _, ind) } + override Node0Impl getValue() { isDef(_, result, address, base, _, _) } + + override predicate isCertain() { isDef(true, _, address, base, _, ind) } } private class IteratorDef extends DefImpl, TIteratorDef { @@ -316,6 +319,7 @@ abstract class UseImpl extends DefOrUseImpl { abstract private class OperandBasedUse extends UseImpl { Operand operand; + BaseSourceVariableInstruction base; bindingset[ind] OperandBasedUse() { any() } @@ -323,50 +327,44 @@ abstract private class OperandBasedUse extends UseImpl { final override predicate hasIndexInBlock(IRBlock block, int index) { // See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this // predicate's implementation. - exists(BaseSourceVariableInstruction base | base = this.getBase() | - if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand() - then - exists(Operand op, int indirectionIndex, int indirection | - indirectionIndex = this.getIndirectionIndex() and - indirection = this.getIndirection() and - op = - min(Operand cand, int i | - isUse(_, cand, base, indirection, indirectionIndex) and - block.getInstruction(i) = cand.getUse() - | - cand order by i - ) and - block.getInstruction(index) = op.getUse() - ) - else operand.getUse() = block.getInstruction(index) - ) + if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand() + then + exists(Operand op, int indirectionIndex, int indirection | + indirectionIndex = this.getIndirectionIndex() and + indirection = this.getIndirection() and + op = + min(Operand cand, int i | + isUse(_, cand, base, indirection, indirectionIndex) and + block.getInstruction(i) = cand.getUse() + | + cand order by i + ) and + block.getInstruction(index) = op.getUse() + ) + else operand.getUse() = block.getInstruction(index) } + final override BaseSourceVariableInstruction getBase() { result = base } + final Operand getOperand() { result = operand } final override Cpp::Location getLocation() { result = operand.getLocation() } } private class DirectUse extends OperandBasedUse, TUseImpl { - DirectUse() { this = TUseImpl(operand, ind) } + DirectUse() { this = TUseImpl(base, operand, ind) } - override int getIndirection() { isUse(_, operand, _, result, ind) } + override int getIndirection() { isUse(_, operand, base, result, ind) } - override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, ind) } - - override predicate isCertain() { isUse(true, operand, _, _, ind) } + override predicate isCertain() { isUse(true, operand, base, _, ind) } override Node getNode() { nodeHasOperand(result, operand, ind) } } private class IteratorUse extends OperandBasedUse, TIteratorUse { - BaseSourceVariableInstruction container; + IteratorUse() { this = TIteratorUse(operand, base, ind) } - IteratorUse() { this = TIteratorUse(operand, container, ind) } - - override int getIndirection() { isIteratorUse(container, operand, result, ind) } - - override BaseSourceVariableInstruction getBase() { result = container } + override int getIndirection() { isIteratorUse(base, operand, result, ind) } override predicate isCertain() { none() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll index b823adf3e3c..60cb843b61f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll @@ -146,14 +146,6 @@ int countIndirectionsForCppType(LanguageType langType) { ) } -/** - * A `CallInstruction` that calls an allocation function such - * as `malloc` or `operator new`. - */ -class AllocationInstruction extends CallInstruction { - AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction } -} - private predicate isIndirectionType(Type t) { t instanceof Indirection } private predicate hasUnspecifiedBaseType(Indirection t, Type base) { @@ -368,7 +360,7 @@ newtype TBaseSourceVariable = // Each IR variable gets its own source variable TBaseIRVariable(IRVariable var) or // Each allocation gets its own source variable - TBaseCallVariable(AllocationInstruction call) + TBaseCallVariable(CallInstruction call) { not call.getResultIRType() instanceof IRVoidType } abstract private class AbstractBaseSourceVariable extends TBaseSourceVariable { /** Gets a textual representation of this element. */ @@ -396,11 +388,11 @@ class BaseIRVariable extends AbstractBaseSourceVariable, TBaseIRVariable { } class BaseCallVariable extends AbstractBaseSourceVariable, TBaseCallVariable { - AllocationInstruction call; + CallInstruction call; BaseCallVariable() { this = TBaseCallVariable(call) } - AllocationInstruction getCallInstruction() { result = call } + CallInstruction getCallInstruction() { result = call } override string toString() { result = call.toString() } @@ -504,8 +496,7 @@ private class BaseIRVariableInstruction extends BaseSourceVariableInstruction, override BaseIRVariable getBaseSourceVariable() { result.getIRVariable() = this.getIRVariable() } } -private class BaseAllocationInstruction extends BaseSourceVariableInstruction, AllocationInstruction -{ +private class BaseCallInstruction extends BaseSourceVariableInstruction, CallInstruction { override BaseCallVariable getBaseSourceVariable() { result.getCallInstruction() = this } }