Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 36 additions & 38 deletions cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -265,15 +266,17 @@ abstract class DefImpl extends DefOrUseImpl {
}

private class DirectDef extends DefImpl, TDefImpl {
DirectDef() { this = TDefImpl(address, ind) }
BaseSourceVariableInstruction base;

DirectDef() { this = TDefImpl(base, address, ind) }

override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
override BaseSourceVariableInstruction getBase() { result = base }

override int getIndirection() { isDef(_, _, address, _, result, ind) }
override int getIndirection() { isDef(_, _, address, base, result, ind) }

override Node0Impl getValue() { isDef(_, result, address, _, _, _) }
override Node0Impl getValue() { isDef(_, result, address, base, _, _) }

override predicate isCertain() { isDef(true, _, address, _, _, ind) }
override predicate isCertain() { isDef(true, _, address, base, _, ind) }
}

private class IteratorDef extends DefImpl, TIteratorDef {
Expand Down Expand Up @@ -316,57 +319,52 @@ abstract class UseImpl extends DefOrUseImpl {

abstract private class OperandBasedUse extends UseImpl {
Operand operand;
BaseSourceVariableInstruction base;

bindingset[ind]
OperandBasedUse() { any() }

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) }

override int getIndirection() { isUse(_, operand, _, result, ind) }
DirectUse() { this = TUseImpl(base, operand, ind) }

override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, ind) }
override int getIndirection() { isUse(_, operand, base, 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, container, ind) }
IteratorUse() { this = TIteratorUse(operand, base, 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() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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() }

Expand Down Expand Up @@ -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 }
}

Expand Down