@@ -678,6 +678,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
678
678
679
679
class CcNoCall = CallContextNoCall ;
680
680
681
+ class CcReturn = CallContextReturn ;
682
+
681
683
Cc ccNone ( ) { result instanceof CallContextAny }
682
684
683
685
CcCall ccSomeCall ( ) { result instanceof CallContextSomeCall }
@@ -1338,6 +1340,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1338
1340
* or summarized as a single read step with before and after types recorded
1339
1341
* in the `ReadStepTypesOption` parameter.
1340
1342
* - Types are checked using the `compatibleTypes()` relation.
1343
+ * - Call contexts are taken into account.
1341
1344
*/
1342
1345
private module Final {
1343
1346
/**
@@ -1348,8 +1351,12 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1348
1351
* If a read step was taken, then `read` captures the `Content`, the
1349
1352
* container type, and the content type.
1350
1353
*/
1351
- predicate parameterValueFlow ( ParamNode p , Node node , ReadStepTypesOption read , string model ) {
1352
- parameterValueFlow0 ( p , node , read , model ) and
1354
+ predicate parameterValueFlow (
1355
+ ParamNode p , Node node , ReadStepTypesOption read , string model ,
1356
+ CachedCallContextSensitivity:: CcNoCall ctx
1357
+ ) {
1358
+ parameterValueFlow0 ( p , node , read , model , ctx ) and
1359
+ Cand:: cand ( p , node ) and
1353
1360
if node instanceof CastingNode
1354
1361
then
1355
1362
// normal flow through
@@ -1369,84 +1376,116 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1369
1376
1370
1377
pragma [ nomagic]
1371
1378
private predicate parameterValueFlow0 (
1372
- ParamNode p , Node node , ReadStepTypesOption read , string model
1379
+ ParamNode p , Node node , ReadStepTypesOption read , string model ,
1380
+ CachedCallContextSensitivity:: CcNoCall ctx
1373
1381
) {
1374
1382
p = node and
1375
1383
Cand:: cand ( p , _) and
1376
1384
read = TReadStepTypesNone ( ) and
1377
- model = ""
1385
+ model = "" and
1386
+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx )
1378
1387
or
1379
1388
// local flow
1380
1389
exists ( Node mid , string model1 , string model2 |
1381
- parameterValueFlow ( p , mid , read , model1 ) and
1390
+ parameterValueFlow ( p , mid , read , model1 , ctx ) and
1382
1391
simpleLocalFlowStep ( mid , node , model2 ) and
1383
1392
validParameterAliasStep ( mid , node ) and
1384
1393
model = mergeModels ( model1 , model2 )
1385
1394
)
1386
1395
or
1387
1396
// read
1388
1397
exists ( Node mid |
1389
- parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model ) and
1398
+ parameterValueFlow ( p , mid , TReadStepTypesNone ( ) , model , ctx ) and
1390
1399
readStepWithTypes ( mid , read .getContainerType ( ) , read .getContent ( ) , node ,
1391
1400
read .getContentType ( ) ) and
1392
1401
Cand:: parameterValueFlowReturnCand ( p , _, true ) and
1393
1402
compatibleTypesFilter ( getNodeDataFlowType ( p ) , read .getContainerType ( ) )
1394
1403
)
1395
1404
or
1396
- parameterValueFlow0_0 ( TReadStepTypesNone ( ) , p , node , read , model )
1405
+ parameterValueFlow0_0 ( TReadStepTypesNone ( ) , p , node , read , model , ctx )
1406
+ }
1407
+
1408
+ bindingset [ ctx1, ctx2]
1409
+ pragma [ inline_late]
1410
+ private CachedCallContextSensitivity:: CcNoCall mergeContexts (
1411
+ CachedCallContextSensitivity:: CcNoCall ctx1 , CachedCallContextSensitivity:: CcNoCall ctx2
1412
+ ) {
1413
+ if CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx1 )
1414
+ then result = ctx2
1415
+ else
1416
+ if CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( ctx2 )
1417
+ then result = ctx1
1418
+ else
1419
+ // check that `ctx1` is compatible with `ctx2` for at least _some_ outer call,
1420
+ // and then (arbitrarily) continue with `ctx2`
1421
+ exists ( DataFlowCall someOuterCall , DataFlowCallable callable |
1422
+ someOuterCall =
1423
+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , ctx1 ) and
1424
+ someOuterCall =
1425
+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , ctx2 ) and
1426
+ result = ctx2
1427
+ )
1397
1428
}
1398
1429
1399
1430
pragma [ nomagic]
1400
1431
private predicate parameterValueFlow0_0 (
1401
1432
ReadStepTypesOption mustBeNone , ParamNode p , Node node , ReadStepTypesOption read ,
1402
- string model
1433
+ string model , CachedCallContextSensitivity :: CcNoCall ctx
1403
1434
) {
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 )
1435
+ exists (
1436
+ ArgNode arg , string model1 , string model2 , CachedCallContextSensitivity:: CcNoCall ctx1 ,
1437
+ CachedCallContextSensitivity:: CcNoCall ctx2
1438
+ |
1439
+ model = mergeModels ( model1 , model2 ) and
1440
+ ctx = mergeContexts ( ctx1 , ctx2 )
1441
+ |
1442
+ // flow through: no prior read
1443
+ parameterValueFlowArg ( p , arg , mustBeNone , model1 , ctx1 ) and
1444
+ argumentValueFlowsThrough ( arg , read , node , model2 , ctx2 )
1445
+ or
1446
+ // flow through: no read inside method
1447
+ parameterValueFlowArg ( p , arg , read , model1 , ctx1 ) and
1448
+ argumentValueFlowsThrough ( arg , mustBeNone , node , model2 , ctx2 )
1416
1449
)
1417
1450
}
1418
1451
1419
1452
pragma [ nomagic]
1420
1453
private predicate parameterValueFlowArg (
1421
- ParamNode p , ArgNode arg , ReadStepTypesOption read , string model
1454
+ ParamNode p , ArgNode arg , ReadStepTypesOption read , string model ,
1455
+ CachedCallContextSensitivity:: CcNoCall ctx
1422
1456
) {
1423
- parameterValueFlow ( p , arg , read , model ) and
1457
+ parameterValueFlow ( p , arg , read , model , ctx ) and
1424
1458
Cand:: argumentValueFlowsThroughCand ( arg , _, _)
1425
1459
}
1426
1460
1427
1461
pragma [ nomagic]
1428
1462
private predicate argumentValueFlowsThrough0 (
1429
- DataFlowCall call , ArgNode arg , ReturnKind kind , ReadStepTypesOption read , string model
1463
+ DataFlowCall call , ArgNode arg , ReturnKind kind , ReadStepTypesOption read , string model ,
1464
+ CachedCallContextSensitivity:: CcNoCall outerCtx
1430
1465
) {
1431
- exists ( ParamNode param | viableParamArg ( call , param , arg ) |
1432
- parameterValueFlowReturn ( param , kind , read , model )
1466
+ exists (
1467
+ ParamNode param , DataFlowCallable callable ,
1468
+ CachedCallContextSensitivity:: CcNoCall innerCtx
1469
+ |
1470
+ viableParamArg ( call , param , arg ) and
1471
+ parameterValueFlowReturn ( param , kind , read , model , innerCtx ) and
1472
+ callable = nodeGetEnclosingCallable ( param ) and
1473
+ outerCtx = CachedCallContextSensitivity:: getCallContextReturn ( callable , call )
1474
+ |
1475
+ CachedCallContextSensitivity:: viableImplNotCallContextReducedReverse ( innerCtx )
1476
+ or
1477
+ call =
1478
+ CachedCallContextSensitivity:: viableImplCallContextReducedReverse ( callable , innerCtx )
1433
1479
)
1434
1480
}
1435
1481
1436
- /**
1437
- * Holds if `arg` flows to `out` through a call using only
1438
- * value-preserving steps and possibly a single read step, not taking
1439
- * call contexts into account.
1440
- *
1441
- * If a read step was taken, then `read` captures the `Content`, the
1442
- * container type, and the content type.
1443
- */
1444
- cached
1445
- predicate argumentValueFlowsThrough (
1446
- ArgNode arg , ReadStepTypesOption read , Node out , string model
1482
+ pragma [ nomagic]
1483
+ private predicate argumentValueFlowsThrough (
1484
+ ArgNode arg , ReadStepTypesOption read , Node out , string model ,
1485
+ CachedCallContextSensitivity:: CcNoCall ctx
1447
1486
) {
1448
1487
exists ( DataFlowCall call , ReturnKind kind |
1449
- argumentValueFlowsThrough0 ( call , arg , kind , read , model ) and
1488
+ argumentValueFlowsThrough0 ( call , arg , kind , read , model , ctx ) and
1450
1489
out = getAnOutNode ( call , kind )
1451
1490
|
1452
1491
// normal flow through
@@ -1459,6 +1498,21 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1459
1498
)
1460
1499
}
1461
1500
1501
+ /**
1502
+ * Holds if `arg` flows to `out` through a call using only
1503
+ * value-preserving steps and possibly a single read step, not taking
1504
+ * call contexts into account.
1505
+ *
1506
+ * If a read step was taken, then `read` captures the `Content`, the
1507
+ * container type, and the content type.
1508
+ */
1509
+ cached
1510
+ predicate argumentValueFlowsThrough (
1511
+ ArgNode arg , ReadStepTypesOption read , Node out , string model
1512
+ ) {
1513
+ argumentValueFlowsThrough ( arg , read , out , model , _)
1514
+ }
1515
+
1462
1516
/**
1463
1517
* Holds if `arg` flows to `out` through a call using only
1464
1518
* value-preserving steps and a single read step, not taking call
@@ -1479,10 +1533,11 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1479
1533
* container type, and the content type.
1480
1534
*/
1481
1535
private predicate parameterValueFlowReturn (
1482
- ParamNode p , ReturnKind kind , ReadStepTypesOption read , string model
1536
+ ParamNode p , ReturnKind kind , ReadStepTypesOption read , string model ,
1537
+ CachedCallContextSensitivity:: CcNoCall ctx
1483
1538
) {
1484
1539
exists ( ReturnNode ret |
1485
- parameterValueFlow ( p , ret , read , model ) and
1540
+ parameterValueFlow ( p , ret , read , model , ctx ) and
1486
1541
kind = ret .getKind ( )
1487
1542
)
1488
1543
}
@@ -1498,7 +1553,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
1498
1553
* node `n`, in the same callable, using only value-preserving steps.
1499
1554
*/
1500
1555
private predicate parameterValueFlowsToPreUpdate ( ParamNode p , PostUpdateNode n ) {
1501
- parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _)
1556
+ parameterValueFlow ( p , n .getPreUpdateNode ( ) , TReadStepTypesNone ( ) , _, _ )
1502
1557
}
1503
1558
1504
1559
cached
0 commit comments