@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
11351135 DataFlowCall call , ArgNodeEx arg , ParamNodeEx p , boolean allowsFieldFlow
11361136 ) ;
11371137
1138- bindingset [ node, state, t , ap]
1139- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) ;
1138+ bindingset [ node, state, t0 , ap]
1139+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) ;
11401140
11411141 bindingset [ typ, contentType]
11421142 predicate typecheckStore ( Typ typ , DataFlowType contentType ) ;
@@ -1199,17 +1199,21 @@ module Impl<FullStateConfigSig Config> {
11991199 NodeEx node , FlowState state , Cc cc , ParamNodeOption summaryCtx , TypOption argT ,
12001200 ApOption argAp , Typ t , Ap ap , ApApprox apa
12011201 ) {
1202- fwdFlow0 ( node , state , cc , summaryCtx , argT , argAp , t , ap , apa ) and
1203- PrevStage:: revFlow ( node , state , apa ) and
1204- filter ( node , state , t , ap )
1202+ fwdFlow1 ( node , state , cc , summaryCtx , argT , argAp , _, t , ap , apa )
12051203 }
12061204
1207- pragma [ inline]
1208- additional predicate fwdFlow (
1205+ private predicate fwdFlow1 (
12091206 NodeEx node , FlowState state , Cc cc , ParamNodeOption summaryCtx , TypOption argT ,
1210- ApOption argAp , Typ t , Ap ap
1207+ ApOption argAp , Typ t0 , Typ t , Ap ap , ApApprox apa
12111208 ) {
1212- fwdFlow ( node , state , cc , summaryCtx , argT , argAp , t , ap , _)
1209+ fwdFlow0 ( node , state , cc , summaryCtx , argT , argAp , t0 , ap , apa ) and
1210+ PrevStage:: revFlow ( node , state , apa ) and
1211+ filter ( node , state , t0 , ap , t )
1212+ }
1213+
1214+ pragma [ nomagic]
1215+ private predicate typeStrengthen ( Typ t0 , Ap ap , Typ t ) {
1216+ fwdFlow1 ( _, _, _, _, _, _, t0 , t , ap , _) and t0 != t
12131217 }
12141218
12151219 pragma [ assume_small_delta]
@@ -1339,6 +1343,11 @@ module Impl<FullStateConfigSig Config> {
13391343 private predicate fwdFlowConsCand ( Typ t2 , Ap cons , Content c , Typ t1 , Ap tail ) {
13401344 fwdFlowStore ( _, t1 , tail , c , t2 , _, _, _, _, _, _) and
13411345 cons = apCons ( c , t1 , tail )
1346+ or
1347+ exists ( Typ t0 |
1348+ typeStrengthen ( t0 , cons , t2 ) and
1349+ fwdFlowConsCand ( t0 , cons , c , t1 , tail )
1350+ )
13421351 }
13431352
13441353 pragma [ nomagic]
@@ -1359,7 +1368,7 @@ module Impl<FullStateConfigSig Config> {
13591368 ParamNodeOption summaryCtx , TypOption argT , ApOption argAp
13601369 ) {
13611370 exists ( ApHeadContent apc |
1362- fwdFlow ( node1 , state , cc , summaryCtx , argT , argAp , t , ap ) and
1371+ fwdFlow ( node1 , state , cc , summaryCtx , argT , argAp , t , ap , _ ) and
13631372 apc = getHeadContent ( ap ) and
13641373 readStepCand0 ( node1 , apc , c , node2 )
13651374 )
@@ -1520,14 +1529,14 @@ module Impl<FullStateConfigSig Config> {
15201529 NodeEx node , FlowState state , ReturnCtx returnCtx , ApOption returnAp , Ap ap
15211530 ) {
15221531 revFlow0 ( node , state , returnCtx , returnAp , ap ) and
1523- fwdFlow ( node , state , _, _, _, _, _, ap )
1532+ fwdFlow ( node , state , _, _, _, _, _, ap , _ )
15241533 }
15251534
15261535 pragma [ nomagic]
15271536 private predicate revFlow0 (
15281537 NodeEx node , FlowState state , ReturnCtx returnCtx , ApOption returnAp , Ap ap
15291538 ) {
1530- fwdFlow ( node , state , _, _, _, _, _, ap ) and
1539+ fwdFlow ( node , state , _, _, _, _, _, ap , _ ) and
15311540 sinkNode ( node , state ) and
15321541 (
15331542 if hasSinkCallCtx ( )
@@ -1780,13 +1789,13 @@ module Impl<FullStateConfigSig Config> {
17801789 boolean fwd , int nodes , int fields , int conscand , int states , int tuples
17811790 ) {
17821791 fwd = true and
1783- nodes = count ( NodeEx node | fwdFlow ( node , _, _, _, _, _, _, _) ) and
1792+ nodes = count ( NodeEx node | fwdFlow ( node , _, _, _, _, _, _, _, _ ) ) and
17841793 fields = count ( Content f0 | fwdConsCand ( f0 , _, _) ) and
17851794 conscand = count ( Content f0 , Typ t , Ap ap | fwdConsCand ( f0 , t , ap ) ) and
1786- states = count ( FlowState state | fwdFlow ( _, state , _, _, _, _, _, _) ) and
1795+ states = count ( FlowState state | fwdFlow ( _, state , _, _, _, _, _, _, _ ) ) and
17871796 tuples =
17881797 count ( NodeEx n , FlowState state , Cc cc , ParamNodeOption summaryCtx , TypOption argT ,
1789- ApOption argAp , Typ t , Ap ap | fwdFlow ( n , state , cc , summaryCtx , argT , argAp , t , ap ) )
1798+ ApOption argAp , Typ t , Ap ap | fwdFlow ( n , state , cc , summaryCtx , argT , argAp , t , ap , _ ) )
17901799 or
17911800 fwd = false and
17921801 nodes = count ( NodeEx node | revFlow ( node , _, _, _, _) ) and
@@ -1963,10 +1972,10 @@ module Impl<FullStateConfigSig Config> {
19631972 )
19641973 }
19651974
1966- bindingset [ node, state, t , ap]
1967- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
1975+ bindingset [ node, state, t0 , ap]
1976+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
19681977 PrevStage:: revFlowState ( state ) and
1969- exists ( t ) and
1978+ t0 = t and
19701979 exists ( ap ) and
19711980 not stateBarrier ( node , state ) and
19721981 (
@@ -2197,8 +2206,8 @@ module Impl<FullStateConfigSig Config> {
21972206 import BooleanCallContext
21982207
21992208 predicate localStep (
2200- NodeEx node1 , FlowState state1 , NodeEx node2 , FlowState state2 , boolean preservesValue ,
2201- DataFlowType t , LocalCc lcc
2209+ NodeEx node1 , FlowState state1 , NodeEx node2 , FlowState state2 , boolean preservesValue , Typ t ,
2210+ LocalCc lcc
22022211 ) {
22032212 localFlowBigStep ( node1 , state1 , node2 , state2 , preservesValue , t , _) and
22042213 exists ( lcc )
@@ -2218,10 +2227,16 @@ module Impl<FullStateConfigSig Config> {
22182227 )
22192228 }
22202229
2221- bindingset [ node, state, t , ap]
2222- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
2230+ bindingset [ node, state, t0 , ap]
2231+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
22232232 exists ( state ) and
2224- ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t ) else any ( ) ) and
2233+ // We can get away with not using type strengthening here, since we aren't
2234+ // going to use the tracked types in the construction of Stage 4 access
2235+ // paths. For Stage 4 and onwards, the tracked types must be consistent as
2236+ // the cons candidates including types are used to construct subsequent
2237+ // access path approximations.
2238+ t0 = t and
2239+ ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t0 ) else any ( ) ) and
22252240 (
22262241 notExpectsContent ( node )
22272242 or
@@ -2241,6 +2256,16 @@ module Impl<FullStateConfigSig Config> {
22412256 import MkStage< Stage2 > :: Stage< Stage3Param >
22422257 }
22432258
2259+ bindingset [ node, t0]
2260+ private predicate strengthenType ( NodeEx node , DataFlowType t0 , DataFlowType t ) {
2261+ if castingNodeEx ( node )
2262+ then
2263+ exists ( DataFlowType nt | nt = node .getDataFlowType ( ) |
2264+ if typeStrongerThan ( nt , t0 ) then t = nt else ( compatibleTypes ( nt , t0 ) and t = t0 )
2265+ )
2266+ else t = t0
2267+ }
2268+
22442269 private module Stage4Param implements MkStage< Stage3 > :: StageParam {
22452270 private module PrevStage = Stage3;
22462271
@@ -2274,8 +2299,8 @@ module Impl<FullStateConfigSig Config> {
22742299
22752300 pragma [ nomagic]
22762301 predicate localStep (
2277- NodeEx node1 , FlowState state1 , NodeEx node2 , FlowState state2 , boolean preservesValue ,
2278- DataFlowType t , LocalCc lcc
2302+ NodeEx node1 , FlowState state1 , NodeEx node2 , FlowState state2 , boolean preservesValue , Typ t ,
2303+ LocalCc lcc
22792304 ) {
22802305 localFlowBigStep ( node1 , state1 , node2 , state2 , preservesValue , t , _) and
22812306 PrevStage:: revFlow ( node1 , pragma [ only_bind_into ] ( state1 ) , _) and
@@ -2333,11 +2358,11 @@ module Impl<FullStateConfigSig Config> {
23332358 )
23342359 }
23352360
2336- bindingset [ node, state, t , ap]
2337- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
2361+ bindingset [ node, state, t0 , ap]
2362+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
23382363 exists ( state ) and
23392364 not clear ( node , ap ) and
2340- ( if castingNodeEx ( node ) then compatibleTypes ( node . getDataFlowType ( ) , t ) else any ( ) ) and
2365+ strengthenType ( node , t0 , t ) and
23412366 (
23422367 notExpectsContent ( node )
23432368 or
@@ -2365,7 +2390,7 @@ module Impl<FullStateConfigSig Config> {
23652390 exists ( AccessPathFront apf |
23662391 Stage4:: revFlow ( node , state , TReturnCtxMaybeFlowThrough ( _) , _, apf ) and
23672392 Stage4:: fwdFlow ( node , state , any ( Stage4:: CcCall ccc ) , _, _, TAccessPathFrontSome ( argApf ) , _,
2368- apf )
2393+ apf , _ )
23692394 )
23702395 }
23712396
@@ -2579,8 +2604,8 @@ module Impl<FullStateConfigSig Config> {
25792604 import LocalCallContext
25802605
25812606 predicate localStep (
2582- NodeEx node1 , FlowState state1 , NodeEx node2 , FlowState state2 , boolean preservesValue ,
2583- DataFlowType t , LocalCc lcc
2607+ NodeEx node1 , FlowState state1 , NodeEx node2 , FlowState state2 , boolean preservesValue , Typ t ,
2608+ LocalCc lcc
25842609 ) {
25852610 localFlowBigStep ( node1 , state1 , node2 , state2 , preservesValue , t , lcc ) and
25862611 PrevStage:: revFlow ( node1 , pragma [ only_bind_into ] ( state1 ) , _) and
@@ -2609,9 +2634,9 @@ module Impl<FullStateConfigSig Config> {
26092634 )
26102635 }
26112636
2612- bindingset [ node, state, t , ap]
2613- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
2614- ( if castingNodeEx ( node ) then compatibleTypes ( node . getDataFlowType ( ) , t ) else any ( ) ) and
2637+ bindingset [ node, state, t0 , ap]
2638+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
2639+ strengthenType ( node , t0 , t ) and
26152640 exists ( state ) and
26162641 exists ( ap )
26172642 }
@@ -2632,7 +2657,7 @@ module Impl<FullStateConfigSig Config> {
26322657 Stage5:: parameterMayFlowThrough ( p , _) and
26332658 Stage5:: revFlow ( n , state , TReturnCtxMaybeFlowThrough ( _) , _, apa0 ) and
26342659 Stage5:: fwdFlow ( n , state , any ( CallContextCall ccc ) , TParamNodeSome ( p .asNode ( ) ) , _,
2635- TAccessPathApproxSome ( apa ) , _, apa0 )
2660+ TAccessPathApproxSome ( apa ) , _, apa0 , _ )
26362661 )
26372662 }
26382663
@@ -2649,7 +2674,7 @@ module Impl<FullStateConfigSig Config> {
26492674 TSummaryCtxSome ( ParamNodeEx p , FlowState state , DataFlowType t , AccessPath ap ) {
26502675 exists ( AccessPathApprox apa | ap .getApprox ( ) = apa |
26512676 Stage5:: parameterMayFlowThrough ( p , apa ) and
2652- Stage5:: fwdFlow ( p , state , _, _, _ , _, t , apa ) and
2677+ Stage5:: fwdFlow ( p , state , _, _, Option < DataFlowType > :: some ( t ) , _, _ , apa , _ ) and
26532678 Stage5:: revFlow ( p , state , _)
26542679 )
26552680 }
@@ -2820,9 +2845,7 @@ module Impl<FullStateConfigSig Config> {
28202845 ap = TAccessPathNil ( )
28212846 or
28222847 // ... or a step from an existing PathNode to another node.
2823- pathStep ( _, node , state , cc , sc , t , ap ) and
2824- Stage5:: revFlow ( node , state , ap .getApprox ( ) ) and
2825- ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t ) else any ( ) )
2848+ pathStep ( _, node , state , cc , sc , t , ap )
28262849 } or
28272850 TPathNodeSink ( NodeEx node , FlowState state ) {
28282851 exists ( PathNodeMid sink |
@@ -3340,13 +3363,24 @@ module Impl<FullStateConfigSig Config> {
33403363 ap = mid .getAp ( )
33413364 }
33423365
3366+ private predicate pathStep (
3367+ PathNodeMid mid , NodeEx node , FlowState state , CallContext cc , SummaryCtx sc , DataFlowType t ,
3368+ AccessPath ap
3369+ ) {
3370+ exists ( DataFlowType t0 |
3371+ pathStep0 ( mid , node , state , cc , sc , t0 , ap ) and
3372+ Stage5:: revFlow ( node , state , ap .getApprox ( ) ) and
3373+ strengthenType ( node , t0 , t )
3374+ )
3375+ }
3376+
33433377 /**
33443378 * Holds if data may flow from `mid` to `node`. The last step in or out of
33453379 * a callable is recorded by `cc`.
33463380 */
33473381 pragma [ assume_small_delta]
33483382 pragma [ nomagic]
3349- private predicate pathStep (
3383+ private predicate pathStep0 (
33503384 PathNodeMid mid , NodeEx node , FlowState state , CallContext cc , SummaryCtx sc , DataFlowType t ,
33513385 AccessPath ap
33523386 ) {
@@ -3964,7 +3998,7 @@ module Impl<FullStateConfigSig Config> {
39643998 ap = TPartialNil ( ) and
39653999 exists ( explorationLimit ( ) )
39664000 or
3967- partialPathNodeMk0 ( node , state , cc , sc1 , sc2 , sc3 , sc4 , t , ap ) and
4001+ partialPathStep ( _ , node , state , cc , sc1 , sc2 , sc3 , sc4 , t , ap ) and
39684002 distSrc ( node .getEnclosingCallable ( ) ) <= explorationLimit ( )
39694003 } or
39704004 TPartialPathNodeRev (
@@ -3990,21 +4024,35 @@ module Impl<FullStateConfigSig Config> {
39904024 }
39914025
39924026 pragma [ nomagic]
3993- private predicate partialPathNodeMk0 (
3994- NodeEx node , FlowState state , CallContext cc , TSummaryCtx1 sc1 , TSummaryCtx2 sc2 ,
3995- TSummaryCtx3 sc3 , TSummaryCtx4 sc4 , DataFlowType t , PartialAccessPath ap
4027+ private predicate partialPathStep (
4028+ PartialPathNodeFwd mid , NodeEx node , FlowState state , CallContext cc , TSummaryCtx1 sc1 ,
4029+ TSummaryCtx2 sc2 , TSummaryCtx3 sc3 , TSummaryCtx4 sc4 , DataFlowType t , PartialAccessPath ap
39964030 ) {
3997- partialPathStep ( _, node , state , cc , sc1 , sc2 , sc3 , sc4 , t , ap ) and
4031+ partialPathStep1 ( mid , node , state , cc , sc1 , sc2 , sc3 , sc4 , _, t , ap )
4032+ }
4033+
4034+ pragma [ nomagic]
4035+ private predicate partialPathStep1 (
4036+ PartialPathNodeFwd mid , NodeEx node , FlowState state , CallContext cc , TSummaryCtx1 sc1 ,
4037+ TSummaryCtx2 sc2 , TSummaryCtx3 sc3 , TSummaryCtx4 sc4 , DataFlowType t0 , DataFlowType t ,
4038+ PartialAccessPath ap
4039+ ) {
4040+ partialPathStep0 ( mid , node , state , cc , sc1 , sc2 , sc3 , sc4 , t0 , ap ) and
39984041 not fullBarrier ( node ) and
39994042 not stateBarrier ( node , state ) and
40004043 not clearsContentEx ( node , ap .getHead ( ) ) and
40014044 (
40024045 notExpectsContent ( node ) or
40034046 expectsContentEx ( node , ap .getHead ( ) )
40044047 ) and
4005- if node .asNode ( ) instanceof CastingNode
4006- then compatibleTypes ( node .getDataFlowType ( ) , t )
4007- else any ( )
4048+ strengthenType ( node , t0 , t )
4049+ }
4050+
4051+ pragma [ nomagic]
4052+ private predicate partialPathTypeStrengthen (
4053+ DataFlowType t0 , PartialAccessPath ap , DataFlowType t
4054+ ) {
4055+ partialPathStep1 ( _, _, _, _, _, _, _, _, t0 , t , ap ) and t0 != t
40084056 }
40094057
40104058 /**
@@ -4183,7 +4231,8 @@ module Impl<FullStateConfigSig Config> {
41834231 }
41844232 }
41854233
4186- private predicate partialPathStep (
4234+ pragma [ nomagic]
4235+ private predicate partialPathStep0 (
41874236 PartialPathNodeFwd mid , NodeEx node , FlowState state , CallContext cc , TSummaryCtx1 sc1 ,
41884237 TSummaryCtx2 sc2 , TSummaryCtx3 sc3 , TSummaryCtx4 sc4 , DataFlowType t , PartialAccessPath ap
41894238 ) {
@@ -4309,6 +4358,11 @@ module Impl<FullStateConfigSig Config> {
43094358 DataFlowType t1 , PartialAccessPath ap1 , Content c , DataFlowType t2 , PartialAccessPath ap2
43104359 ) {
43114360 partialPathStoreStep ( _, t1 , ap1 , c , _, t2 , ap2 )
4361+ or
4362+ exists ( DataFlowType t0 |
4363+ partialPathTypeStrengthen ( t0 , ap2 , t2 ) and
4364+ apConsFwd ( t1 , ap1 , c , t0 , ap2 )
4365+ )
43124366 }
43134367
43144368 pragma [ nomagic]
0 commit comments