@@ -628,6 +628,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
628
628
override string toString ( ) {
629
629
exists ( DataFlowCall call | this = TReturn ( _, call ) | result = "CcReturn(" + call + ")" )
630
630
}
631
+
632
+ predicate isReturn ( DataFlowCallable c , DataFlowCall call ) { this = TReturn ( c , call ) }
631
633
}
632
634
633
635
pragma [ nomagic]
@@ -678,6 +680,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
678
680
679
681
class CcNoCall = CallContextNoCall ;
680
682
683
+ class CcReturn = CallContextReturn ;
684
+
681
685
Cc ccNone ( ) { result instanceof CallContextAny }
682
686
683
687
CcCall ccSomeCall ( ) { result instanceof CallContextSomeCall }
@@ -1338,6 +1342,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1338
1342
* or summarized as a single read step with before and after types recorded
1339
1343
* in the `ReadStepTypesOption` parameter.
1340
1344
* - Types are checked using the `compatibleTypes()` relation.
1345
+ * - Call contexts are taken into account.
1341
1346
*/
1342
1347
private module Final {
1343
1348
/**
@@ -1348,8 +1353,12 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1348
1353
* If a read step was taken, then `read` captures the `Content`, the
1349
1354
* container type, and the content type.
1350
1355
*/
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
1353
1362
if node instanceof CastingNode
1354
1363
then
1355
1364
// normal flow through
@@ -1369,67 +1378,128 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1369
1378
1370
1379
pragma [ nomagic]
1371
1380
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
1373
1383
) {
1374
1384
p = node and
1375
1385
Cand:: cand ( p , _) and
1376
1386
read = TReadStepTypesNone ( ) and
1377
- model = ""
1387
+ model = "" and
1388
+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx )
1378
1389
or
1379
1390
// local flow
1380
1391
exists ( Node mid , string model1 , string model2 |
1381
- parameterValueFlow ( p , mid , read , model1 ) and
1392
+ parameterValueFlow ( p , mid , read , model1 , ctx ) and
1382
1393
simpleLocalFlowStep ( mid , node , model2 ) and
1383
1394
validParameterAliasStep ( mid , node ) and
1384
1395
model = mergeModels ( model1 , model2 )
1385
1396
)
1386
1397
or
1387
1398
// read
1388
1399
exists ( Node mid |
1389
- parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model ) and
1400
+ parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model , ctx ) and
1390
1401
readStepWithTypes ( mid , read .getContainerType ( ) , read .getContent ( ) , node ,
1391
1402
read .getContentType ( ) ) and
1392
1403
Cand:: parameterValueFlowReturnCand ( p , _, true ) and
1393
1404
compatibleTypesFilter ( getNodeDataFlowType ( p ) , read .getContainerType ( ) )
1394
1405
)
1395
1406
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
+ )
1397
1430
}
1398
1431
1399
1432
pragma [ nomagic]
1400
1433
private predicate parameterValueFlow0_0 (
1401
1434
ReadStepTypesOption mustBeNone , ParamNode p , Node node , ReadStepTypesOption read ,
1402
- string model
1435
+ string model , CachedCallContextSensitivity :: CcNoCall ctx
1403
1436
) {
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 )
1416
1459
)
1417
1460
}
1418
1461
1419
1462
pragma [ nomagic]
1420
1463
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
1422
1466
) {
1423
- parameterValueFlow ( p , arg , read , model ) and
1467
+ parameterValueFlow ( p , arg , read , model , ctx ) and
1424
1468
Cand:: argumentValueFlowsThroughCand ( arg , _, _)
1425
1469
}
1426
1470
1427
1471
pragma [ nomagic]
1428
1472
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
1430
1475
) {
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 ) )
1433
1503
)
1434
1504
}
1435
1505
@@ -1445,18 +1515,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1445
1515
predicate argumentValueFlowsThrough (
1446
1516
ArgNode arg , ReadStepTypesOption read , Node out , string model
1447
1517
) {
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 )
1460
1519
}
1461
1520
1462
1521
/**
@@ -1479,10 +1538,11 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1479
1538
* container type, and the content type.
1480
1539
*/
1481
1540
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
1483
1543
) {
1484
1544
exists ( ReturnNode ret |
1485
- parameterValueFlow ( p , ret , read , model ) and
1545
+ parameterValueFlow ( p , ret , read , model , ctx ) and
1486
1546
kind = ret .getKind ( )
1487
1547
)
1488
1548
}
@@ -1498,7 +1558,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1498
1558
* node `n`, in the same callable, using only value-preserving steps.
1499
1559
*/
1500
1560
private predicate parameterValueFlowsToPreUpdate ( ParamNode p , PostUpdateNode n ) {
1501
- parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _)
1561
+ parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _, _ )
1502
1562
}
1503
1563
1504
1564
cached
0 commit comments