Skip to content

Commit 9e82ce8

Browse files
committed
C++: Implement 'isUnreachableInCall'.
1 parent 25be9d4 commit 9e82ce8

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,73 @@ class DataFlowCall extends CallInstruction {
854854
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
855855
}
856856

857-
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
857+
module IsUnreachableInCall {
858+
private import semmle.code.cpp.ir.ValueNumbering
859+
private import semmle.code.cpp.controlflow.IRGuards as G
860+
861+
private class ConstantIntegralTypeArgumentNode extends PrimaryArgumentNode {
862+
int value;
863+
864+
ConstantIntegralTypeArgumentNode() {
865+
value = op.getDef().(IntegerConstantInstruction).getValue().toInt()
866+
}
867+
868+
int getValue() { result = value }
869+
}
870+
871+
pragma[nomagic]
872+
private predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
873+
any(G::IRGuardCondition guard).ensuresEq(left, right, k, block, areEqual)
874+
}
875+
876+
pragma[nomagic]
877+
private predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
878+
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
879+
}
880+
881+
predicate isUnreachableInCall(Node n, DataFlowCall call) {
882+
exists(
883+
DirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
884+
IntegerConstantInstruction constant, int k, Operand left, Operand right, IRBlock block
885+
|
886+
// arg flows into `paramNode`
887+
DataFlowImplCommon::viableParamArg(call, paramNode, arg) and
888+
left = constant.getAUse() and
889+
right = valueNumber(paramNode.getInstruction()).getAUse() and
890+
block = n.getBasicBlock()
891+
|
892+
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`
893+
exists(boolean areEqual |
894+
ensuresEq(pragma[only_bind_into](left), pragma[only_bind_into](right),
895+
pragma[only_bind_into](k), pragma[only_bind_into](block), areEqual)
896+
|
897+
// this block ensures that left = right + k, but it holds that `left != right + k`
898+
areEqual = true and
899+
constant.getValue().toInt() != arg.getValue() + k
900+
or
901+
// this block ensures that or `left != right + k`, but it holds that `left = right + k`
902+
areEqual = false and
903+
constant.getValue().toInt() = arg.getValue() + k
904+
)
905+
or
906+
// or there's a guard condition which ensures that the result of `left < right + k` is `isLessThan`
907+
exists(boolean isLessThan |
908+
ensuresLt(pragma[only_bind_into](left), pragma[only_bind_into](right),
909+
pragma[only_bind_into](k), pragma[only_bind_into](block), isLessThan)
910+
|
911+
isLessThan = true and
912+
// this block ensures that `left < right + k`, but it holds that `left >= right + k`
913+
constant.getValue().toInt() >= arg.getValue() + k
914+
or
915+
// this block ensures that `left >= right + k`, but it holds that `left < right + k`
916+
isLessThan = false and
917+
constant.getValue().toInt() < arg.getValue() + k
918+
)
919+
)
920+
}
921+
}
922+
923+
import IsUnreachableInCall
858924

859925
int accessPathLimit() { result = 5 }
860926

0 commit comments

Comments
 (0)