@@ -628,6 +628,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
628628 override string toString ( ) {
629629 exists ( DataFlowCall call | this = TReturn ( _, call ) | result = "CcReturn(" + call + ")" )
630630 }
631+
632+ predicate isReturn ( DataFlowCallable c , DataFlowCall call ) { this = TReturn ( c , call ) }
631633 }
632634
633635 pragma [ nomagic]
@@ -678,6 +680,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
678680
679681 class CcNoCall = CallContextNoCall ;
680682
683+ class CcReturn = CallContextReturn ;
684+
681685 Cc ccNone ( ) { result instanceof CallContextAny }
682686
683687 CcCall ccSomeCall ( ) { result instanceof CallContextSomeCall }
@@ -1338,6 +1342,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
13381342 * or summarized as a single read step with before and after types recorded
13391343 * in the `ReadStepTypesOption` parameter.
13401344 * - Types are checked using the `compatibleTypes()` relation.
1345+ * - Call contexts are taken into account.
13411346 */
13421347 private module Final {
13431348 /**
@@ -1348,8 +1353,12 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
13481353 * If a read step was taken, then `read` captures the `Content`, the
13491354 * container type, and the content type.
13501355 */
1351- predicate parameterValueFlow ( ParamNode p , Node node , ReadStepTypesOption read , string model ) {
1352- parameterValueFlow0 ( p , node , read , model ) and
1356+ predicate parameterValueFlow (
1357+ ParamNode p , Node node , ReadStepTypesOption read , string model ,
1358+ CachedCallContextSensitivity:: CcNoCall ctx
1359+ ) {
1360+ parameterValueFlow0 ( p , node , read , model , ctx ) and
1361+ Cand:: cand ( p , node ) and
13531362 if node instanceof CastingNode
13541363 then
13551364 // normal flow through
@@ -1369,67 +1378,128 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
13691378
13701379 pragma [ nomagic]
13711380 private predicate parameterValueFlow0 (
1372- ParamNode p , Node node , ReadStepTypesOption read , string model
1381+ ParamNode p , Node node , ReadStepTypesOption read , string model ,
1382+ CachedCallContextSensitivity:: CcNoCall ctx
13731383 ) {
13741384 p = node and
13751385 Cand:: cand ( p , _) and
13761386 read = TReadStepTypesNone ( ) and
1377- model = ""
1387+ model = "" and
1388+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx )
13781389 or
13791390 // local flow
13801391 exists ( Node mid , string model1 , string model2 |
1381- parameterValueFlow ( p , mid , read , model1 ) and
1392+ parameterValueFlow ( p , mid , read , model1 , ctx ) and
13821393 simpleLocalFlowStep ( mid , node , model2 ) and
13831394 validParameterAliasStep ( mid , node ) and
13841395 model = mergeModels ( model1 , model2 )
13851396 )
13861397 or
13871398 // read
13881399 exists ( Node mid |
1389- parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model ) and
1400+ parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model , ctx ) and
13901401 readStepWithTypes ( mid , read .getContainerType ( ) , read .getContent ( ) , node ,
13911402 read .getContentType ( ) ) and
13921403 Cand:: parameterValueFlowReturnCand ( p , _, true ) and
13931404 compatibleTypesFilter ( getNodeDataFlowType ( p ) , read .getContainerType ( ) )
13941405 )
13951406 or
1396- parameterValueFlow0_0 ( TReadStepTypesNone ( ) , p , node , read , model )
1407+ parameterValueFlow0_0 ( TReadStepTypesNone ( ) , p , node , read , model , ctx )
1408+ }
1409+
1410+ bindingset [ ctx1, ctx2]
1411+ pragma [ inline_late]
1412+ private CachedCallContextSensitivity:: CcNoCall mergeContexts (
1413+ CachedCallContextSensitivity:: CcNoCall ctx1 , CachedCallContextSensitivity:: CcNoCall ctx2
1414+ ) {
1415+ if CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx1 )
1416+ then result = ctx2
1417+ else
1418+ if CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx2 )
1419+ then result = ctx1
1420+ else
1421+ // check that `ctx1` is compatible with `ctx2` for at least _some_ outer call,
1422+ // and then (arbitrarily) continue with `ctx2`
1423+ exists ( DataFlowCall someOuterCall , DataFlowCallable callable |
1424+ someOuterCall =
1425+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , ctx1 ) and
1426+ someOuterCall =
1427+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , ctx2 ) and
1428+ result = ctx2
1429+ )
13971430 }
13981431
13991432 pragma [ nomagic]
14001433 private predicate parameterValueFlow0_0 (
14011434 ReadStepTypesOption mustBeNone , ParamNode p , Node node , ReadStepTypesOption read ,
1402- string model
1435+ string model , CachedCallContextSensitivity :: CcNoCall ctx
14031436 ) {
1404- // flow through: no prior read
1405- exists ( ArgNode arg , string model1 , string model2 |
1406- parameterValueFlowArg ( p , arg , mustBeNone , model1 ) and
1407- argumentValueFlowsThrough ( arg , read , node , model2 ) and
1408- model = mergeModels ( model1 , model2 )
1409- )
1410- or
1411- // flow through: no read inside method
1412- exists ( ArgNode arg , string model1 , string model2 |
1413- parameterValueFlowArg ( p , arg , read , model1 ) and
1414- argumentValueFlowsThrough ( arg , mustBeNone , node , model2 ) and
1415- model = mergeModels ( model1 , model2 )
1437+ exists (
1438+ DataFlowCall call , DataFlowCallable callable , ArgNode arg , string model1 , string model2 ,
1439+ CachedCallContextSensitivity:: CcNoCall ctx1 , CachedCallContextSensitivity:: CcNoCall ctx2
1440+ |
1441+ model = mergeModels ( model1 , model2 ) and
1442+ (
1443+ // call may restrict the set of call sites that can be returned to
1444+ ctx2 .( CachedCallContextSensitivity:: CcReturn ) .isReturn ( callable , call )
1445+ or
1446+ // call does not restrict the set of call sites that can be returned to
1447+ not exists ( CachedCallContextSensitivity:: CcReturn ret | ret .isReturn ( callable , call ) ) and
1448+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx2 )
1449+ ) and
1450+ ctx = mergeContexts ( ctx1 , ctx2 )
1451+ |
1452+ // flow through: no prior read
1453+ parameterValueFlowArg ( p , arg , mustBeNone , model1 , ctx1 ) and
1454+ argumentValueFlowsThrough ( call , callable , arg , read , node , model2 )
1455+ or
1456+ // flow through: no read inside method
1457+ parameterValueFlowArg ( p , arg , read , model1 , ctx1 ) and
1458+ argumentValueFlowsThrough ( call , callable , arg , mustBeNone , node , model2 )
14161459 )
14171460 }
14181461
14191462 pragma [ nomagic]
14201463 private predicate parameterValueFlowArg (
1421- ParamNode p , ArgNode arg , ReadStepTypesOption read , string model
1464+ ParamNode p , ArgNode arg , ReadStepTypesOption read , string model ,
1465+ CachedCallContextSensitivity:: CcNoCall ctx
14221466 ) {
1423- parameterValueFlow ( p , arg , read , model ) and
1467+ parameterValueFlow ( p , arg , read , model , ctx ) and
14241468 Cand:: argumentValueFlowsThroughCand ( arg , _, _)
14251469 }
14261470
14271471 pragma [ nomagic]
14281472 private predicate argumentValueFlowsThrough0 (
1429- DataFlowCall call , ArgNode arg , ReturnKind kind , ReadStepTypesOption read , string model
1473+ DataFlowCall call , DataFlowCallable callable , ArgNode arg , ReturnKind kind ,
1474+ ReadStepTypesOption read , string model
14301475 ) {
1431- exists ( ParamNode param | viableParamArg ( call , param , arg ) |
1432- parameterValueFlowReturn ( param , kind , read , model )
1476+ exists ( ParamNode param , CachedCallContextSensitivity:: CcNoCall ctx |
1477+ viableParamArg ( call , param , arg ) and
1478+ parameterValueFlowReturn ( param , kind , read , model , ctx ) and
1479+ callable = nodeGetEnclosingCallable ( param )
1480+ |
1481+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx )
1482+ or
1483+ call = CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , ctx )
1484+ )
1485+ }
1486+
1487+ pragma [ nomagic]
1488+ private predicate argumentValueFlowsThrough (
1489+ DataFlowCall call , DataFlowCallable callable , ArgNode arg , ReadStepTypesOption read ,
1490+ Node out , string model
1491+ ) {
1492+ exists ( ReturnKind kind |
1493+ argumentValueFlowsThrough0 ( call , callable , arg , kind , read , model ) and
1494+ out = getAnOutNode ( call , kind )
1495+ |
1496+ // normal flow through
1497+ read = TReadStepTypesNone ( ) and
1498+ compatibleTypesFilter ( getNodeDataFlowType ( arg ) , getNodeDataFlowType ( out ) )
1499+ or
1500+ // getter
1501+ compatibleTypesFilter ( getNodeDataFlowType ( arg ) , read .getContainerType ( ) ) and
1502+ compatibleTypesFilter ( read .getContentType ( ) , getNodeDataFlowType ( out ) )
14331503 )
14341504 }
14351505
@@ -1445,18 +1515,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
14451515 predicate argumentValueFlowsThrough (
14461516 ArgNode arg , ReadStepTypesOption read , Node out , string model
14471517 ) {
1448- exists ( DataFlowCall call , ReturnKind kind |
1449- argumentValueFlowsThrough0 ( call , arg , kind , read , model ) and
1450- out = getAnOutNode ( call , kind )
1451- |
1452- // normal flow through
1453- read = TReadStepTypesNone ( ) and
1454- compatibleTypesFilter ( getNodeDataFlowType ( arg ) , getNodeDataFlowType ( out ) )
1455- or
1456- // getter
1457- compatibleTypesFilter ( getNodeDataFlowType ( arg ) , read .getContainerType ( ) ) and
1458- compatibleTypesFilter ( read .getContentType ( ) , getNodeDataFlowType ( out ) )
1459- )
1518+ argumentValueFlowsThrough ( _, _, arg , read , out , model )
14601519 }
14611520
14621521 /**
@@ -1479,10 +1538,11 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
14791538 * container type, and the content type.
14801539 */
14811540 private predicate parameterValueFlowReturn (
1482- ParamNode p , ReturnKind kind , ReadStepTypesOption read , string model
1541+ ParamNode p , ReturnKind kind , ReadStepTypesOption read , string model ,
1542+ CachedCallContextSensitivity:: CcNoCall ctx
14831543 ) {
14841544 exists ( ReturnNode ret |
1485- parameterValueFlow ( p , ret , read , model ) and
1545+ parameterValueFlow ( p , ret , read , model , ctx ) and
14861546 kind = ret .getKind ( )
14871547 )
14881548 }
@@ -1498,7 +1558,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
14981558 * node `n`, in the same callable, using only value-preserving steps.
14991559 */
15001560 private predicate parameterValueFlowsToPreUpdate ( ParamNode p , PostUpdateNode n ) {
1501- parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _)
1561+ parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _, _ )
15021562 }
15031563
15041564 cached
0 commit comments