@@ -975,42 +975,35 @@ private DataFlow::Node trackSingletonMethodOnInstance(MethodBase method, string
975975 result = trackSingletonMethodOnInstance ( method , name , TypeTracker:: end ( ) )
976976}
977977
978- /** Same as `isInstance`, but includes local must-flow through SSA definitions. */
979- private predicate isInstanceLocalMustFlow ( DataFlow:: Node n , Module tp , boolean exact ) {
980- isInstance ( n , tp , exact )
981- or
982- exists ( DataFlow:: Node mid | isInstanceLocalMustFlow ( mid , tp , exact ) |
983- n .asExpr ( ) = mid .( SsaDefinitionNode ) .getDefinition ( ) .getARead ( )
984- or
985- n .( SsaDefinitionNode ) .getDefinition ( ) .( Ssa:: WriteDefinition ) .assigns ( mid .asExpr ( ) )
986- )
987- }
988-
989978/**
990979 * Holds if `ctx` targets `encl`, which is the enclosing callable of `call`, the receiver
991980 * of `call` is a parameter access, where the corresponding argument of `ctx` is `arg`.
992981 *
993- * `name` is the name of the method being called by `call`.
982+ * `name` is the name of the method being called by `call`, `source` is a
983+ * `LocalSourceNode` that flows to `arg`, and `paramDef` is the SSA definition for the
984+ * parameter that is the receiver of `call`.
994985 */
995986pragma [ nomagic]
996- private predicate argFlowsToReceiver (
997- RelevantCall ctx , ArgumentNode arg , RelevantCall call , Callable encl , string name
987+ private predicate argMustFlowToReceiver (
988+ RelevantCall ctx , DataFlow:: LocalSourceNode source , ArgumentNode arg , SsaDefinitionNode paramDef ,
989+ RelevantCall call , Callable encl , string name
998990) {
999- exists (
1000- ParameterNodeImpl p , SsaDefinitionNode ssaNode , ParameterPosition ppos , ArgumentPosition apos
1001- |
991+ exists ( ParameterNodeImpl p , ParameterPosition ppos , ArgumentPosition apos |
1002992 // the receiver of `call` references `p`
1003- LocalFlow:: localFlowSsaParamInput ( p , ssaNode ) and
1004- flowsToMethodCallReceiver ( pragma [ only_bind_into ] ( call ) , pragma [ only_bind_into ] ( ssaNode ) ,
1005- pragma [ only_bind_into ] ( name ) ) and
993+ exists ( DataFlow:: Node receiver |
994+ LocalFlow:: localFlowSsaParamInput ( p , paramDef ) and
995+ methodCall ( pragma [ only_bind_into ] ( call ) , receiver , pragma [ only_bind_into ] ( name ) ) and
996+ receiver .asExpr ( ) = paramDef .getDefinition ( ) .getARead ( )
997+ ) and
1006998 // `p` is a parameter of `encl`,
1007999 encl = call .getScope ( ) and
10081000 p .isParameterOf ( TCfgScope ( encl ) , ppos ) and
10091001 // `ctx` targets `encl`
10101002 getTarget ( ctx ) = encl and
10111003 // `arg` is the argument for `p` in the call `ctx`
10121004 arg .sourceArgumentOf ( ctx , apos ) and
1013- parameterMatch ( ppos , apos )
1005+ parameterMatch ( ppos , apos ) and
1006+ source .flowsTo ( arg )
10141007 )
10151008}
10161009
@@ -1027,20 +1020,11 @@ private predicate mayBenefitFromCallContextInstance(
10271020 RelevantCall ctx , RelevantCall call , ArgumentNode arg , Callable encl , Module tp , boolean exact ,
10281021 string name
10291022) {
1030- argFlowsToReceiver ( ctx , pragma [ only_bind_into ] ( arg ) , call , encl , pragma [ only_bind_into ] ( name ) ) and
1031- // `arg` has a relevant instance type
1032- isInstanceLocalMustFlow ( arg , tp , exact ) and
1033- exists ( lookupMethod ( tp , pragma [ only_bind_into ] ( name ) ) )
1034- }
1035-
1036- /** Same as `resolveConstantReadAccess`, but includes local must-flow through SSA definitions. */
1037- private predicate resolveConstantReadAccessMustFlow ( DataFlow:: Node n , Module tp ) {
1038- tp = resolveConstantReadAccess ( n .asExpr ( ) .getExpr ( ) )
1039- or
1040- exists ( DataFlow:: Node mid | resolveConstantReadAccessMustFlow ( mid , tp ) |
1041- n .asExpr ( ) = mid .( SsaDefinitionNode ) .getDefinition ( ) .getARead ( )
1042- or
1043- n .( SsaDefinitionNode ) .getDefinition ( ) .( Ssa:: WriteDefinition ) .assigns ( mid .asExpr ( ) )
1023+ exists ( DataFlow:: LocalSourceNode source |
1024+ argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , arg , _, call , encl ,
1025+ pragma [ only_bind_into ] ( name ) ) and
1026+ source = trackInstance ( tp , exact ) and
1027+ exists ( lookupMethod ( tp , pragma [ only_bind_into ] ( name ) ) )
10441028 )
10451029}
10461030
@@ -1057,10 +1041,12 @@ private predicate mayBenefitFromCallContextSingleton(
10571041 RelevantCall ctx , RelevantCall call , ArgumentNode arg , Callable encl , Module tp , boolean exact ,
10581042 string name
10591043) {
1060- argFlowsToReceiver ( ctx , pragma [ only_bind_into ] ( arg ) , call , encl , pragma [ only_bind_into ] ( name ) ) and
1061- // `arg` has a relevant module type
1062- (
1063- resolveConstantReadAccessMustFlow ( arg , tp ) and
1044+ exists ( DataFlow:: LocalSourceNode source |
1045+ argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , pragma [ only_bind_into ] ( arg ) , _, call ,
1046+ encl , pragma [ only_bind_into ] ( name ) ) and
1047+ exists ( lookupSingletonMethod ( tp , pragma [ only_bind_into ] ( name ) , exact ) )
1048+ |
1049+ source = trackModuleAccess ( tp ) and
10641050 exact = true
10651051 or
10661052 exists ( SelfVariable self | arg .asExpr ( ) .getExpr ( ) = self .getAnAccess ( ) |
@@ -1073,8 +1059,7 @@ private predicate mayBenefitFromCallContextSingleton(
10731059 exact = false
10741060 )
10751061 )
1076- ) and
1077- exists ( lookupSingletonMethod ( tp , pragma [ only_bind_into ] ( name ) , exact ) )
1062+ )
10781063}
10791064
10801065/**
@@ -1101,7 +1086,7 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
11011086 exists ( RelevantCall call0 , Callable res |
11021087 call0 = call .asCall ( ) and
11031088 res = result .asCallable ( ) and
1104- res = getTarget ( call0 ) and // make sure to not include e.g. private methods
1089+ result = viableSourceCallable ( call ) and // make sure to not include e.g. private methods
11051090 exists ( Module m , boolean exact , string name |
11061091 mayBenefitFromCallContextInstance ( ctx .asCall ( ) , pragma [ only_bind_into ] ( call0 ) , _, _,
11071092 pragma [ only_bind_into ] ( m ) , exact , pragma [ only_bind_into ] ( name ) ) and
@@ -1113,18 +1098,22 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
11131098 )
11141099 )
11151100 or
1116- // `ctx` cannot provide a type bound
1117- exists ( RelevantCall call0 , RelevantCall ctx0 , ArgumentNode arg , string name |
1101+ // `ctx` cannot provide a type bound, and the receiver of the call is `self`;
1102+ // in this case, still apply an open-world assumption
1103+ exists (
1104+ RelevantCall call0 , RelevantCall ctx0 , ArgumentNode arg , SsaSelfDefinitionNode self ,
1105+ string name
1106+ |
11181107 call0 = call .asCall ( ) and
11191108 ctx0 = ctx .asCall ( ) and
1120- argFlowsToReceiver ( ctx0 , arg , call0 , _, name ) and
1109+ argMustFlowToReceiver ( ctx0 , _ , arg , self , call0 , _, name ) and
11211110 not mayBenefitFromCallContextInstance ( ctx0 , call0 , arg , _, _, _, name ) and
11221111 not mayBenefitFromCallContextSingleton ( ctx0 , call0 , arg , _, _, _, name ) and
11231112 result = viableSourceCallable ( call )
11241113 )
11251114 or
11261115 // library calls should always be able to resolve
1127- argFlowsToReceiver ( ctx .asCall ( ) , _, call .asCall ( ) , _, _) and
1116+ argMustFlowToReceiver ( ctx .asCall ( ) , _ , _ , _, call .asCall ( ) , _, _) and
11281117 result = viableLibraryCallable ( call )
11291118 )
11301119}
0 commit comments