@@ -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
859925int accessPathLimit ( ) { result = 5 }
860926
0 commit comments