@@ -854,7 +854,73 @@ class DataFlowCall extends CallInstruction {
854
854
Function getEnclosingCallable ( ) { result = this .getEnclosingFunction ( ) }
855
855
}
856
856
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
858
924
859
925
int accessPathLimit ( ) { result = 5 }
860
926
0 commit comments