@@ -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,9 +1199,20 @@ 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
1202+ fwdFlow1 ( node , state , cc , summaryCtx , argT , argAp , _, t , ap , apa )
1203+ }
1204+
1205+ private predicate fwdFlow1 (
1206+ NodeEx node , FlowState state , Cc cc , ParamNodeOption summaryCtx , TypOption argT ,
1207+ ApOption argAp , Typ t0 , Typ t , Ap ap , ApApprox apa
1208+ ) {
1209+ fwdFlow0 ( node , state , cc , summaryCtx , argT , argAp , t0 , ap , apa ) and
12031210 PrevStage:: revFlow ( node , state , apa ) and
1204- filter ( node , state , t , ap )
1211+ filter ( node , state , t0 , ap , t )
1212+ }
1213+
1214+ private predicate typeStrengthen ( Typ t0 , Ap ap , Typ t ) {
1215+ fwdFlow1 ( _, _, _, _, _, _, t0 , t , ap , _) and t0 != t
12051216 }
12061217
12071218 pragma [ assume_small_delta]
@@ -1331,6 +1342,11 @@ module Impl<FullStateConfigSig Config> {
13311342 private predicate fwdFlowConsCand ( Typ t2 , Ap cons , Content c , Typ t1 , Ap tail ) {
13321343 fwdFlowStore ( _, t1 , tail , c , t2 , _, _, _, _, _, _) and
13331344 cons = apCons ( c , t1 , tail )
1345+ or
1346+ exists ( Typ t0 |
1347+ typeStrengthen ( t0 , cons , t2 ) and
1348+ fwdFlowConsCand ( t0 , cons , c , t1 , tail )
1349+ )
13341350 }
13351351
13361352 pragma [ nomagic]
@@ -1955,10 +1971,10 @@ module Impl<FullStateConfigSig Config> {
19551971 )
19561972 }
19571973
1958- bindingset [ node, state, t , ap]
1959- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
1974+ bindingset [ node, state, t0 , ap]
1975+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
19601976 PrevStage:: revFlowState ( state ) and
1961- exists ( t ) and
1977+ t0 = t and
19621978 exists ( ap ) and
19631979 not stateBarrier ( node , state ) and
19641980 (
@@ -2210,10 +2226,16 @@ module Impl<FullStateConfigSig Config> {
22102226 )
22112227 }
22122228
2213- bindingset [ node, state, t , ap]
2214- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
2229+ bindingset [ node, state, t0 , ap]
2230+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
22152231 exists ( state ) and
2216- ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t ) else any ( ) ) and
2232+ // We can get away with not using type strengthening here, since we aren't
2233+ // going to use the tracked types in the construction of Stage 4 access
2234+ // paths. For Stage 4 and onwards, the tracked types must be consistent as
2235+ // the cons candidates including types are used to construct subsequent
2236+ // access path approximations.
2237+ t0 = t and
2238+ ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t0 ) else any ( ) ) and
22172239 (
22182240 notExpectsContent ( node )
22192241 or
@@ -2325,11 +2347,18 @@ module Impl<FullStateConfigSig Config> {
23252347 )
23262348 }
23272349
2328- bindingset [ node, state, t , ap]
2329- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
2350+ bindingset [ node, state, t0 , ap]
2351+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
23302352 exists ( state ) and
23312353 not clear ( node , ap ) and
2332- ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t ) else any ( ) ) and
2354+ (
2355+ if castingNodeEx ( node )
2356+ then
2357+ exists ( Typ nt | nt = node .getDataFlowType ( ) |
2358+ if typeStrongerThan ( nt , t0 ) then t = nt else ( compatibleTypes ( nt , t0 ) and t = t0 )
2359+ )
2360+ else t = t0
2361+ ) and
23332362 (
23342363 notExpectsContent ( node )
23352364 or
@@ -2601,9 +2630,16 @@ module Impl<FullStateConfigSig Config> {
26012630 )
26022631 }
26032632
2604- bindingset [ node, state, t, ap]
2605- predicate filter ( NodeEx node , FlowState state , Typ t , Ap ap ) {
2606- ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t ) else any ( ) ) and
2633+ bindingset [ node, state, t0, ap]
2634+ predicate filter ( NodeEx node , FlowState state , Typ t0 , Ap ap , Typ t ) {
2635+ (
2636+ if castingNodeEx ( node )
2637+ then
2638+ exists ( Typ nt | nt = node .getDataFlowType ( ) |
2639+ if typeStrongerThan ( nt , t0 ) then t = nt else ( compatibleTypes ( nt , t0 ) and t = t0 )
2640+ )
2641+ else t = t0
2642+ ) and
26072643 exists ( state ) and
26082644 exists ( ap )
26092645 }
@@ -2812,9 +2848,7 @@ module Impl<FullStateConfigSig Config> {
28122848 ap = TAccessPathNil ( )
28132849 or
28142850 // ... or a step from an existing PathNode to another node.
2815- pathStep ( _, node , state , cc , sc , t , ap ) and
2816- Stage5:: revFlow ( node , state , ap .getApprox ( ) ) and
2817- ( if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , t ) else any ( ) )
2851+ pathStep ( _, node , state , cc , sc , t , ap )
28182852 } or
28192853 TPathNodeSink ( NodeEx node , FlowState state ) {
28202854 exists ( PathNodeMid sink |
@@ -3332,13 +3366,31 @@ module Impl<FullStateConfigSig Config> {
33323366 ap = mid .getAp ( )
33333367 }
33343368
3369+ private predicate pathStep (
3370+ PathNodeMid mid , NodeEx node , FlowState state , CallContext cc , SummaryCtx sc , DataFlowType t ,
3371+ AccessPath ap
3372+ ) {
3373+ exists ( DataFlowType t0 |
3374+ pathStep0 ( mid , node , state , cc , sc , t0 , ap ) and
3375+ Stage5:: revFlow ( node , state , ap .getApprox ( ) ) and
3376+ (
3377+ if castingNodeEx ( node )
3378+ then
3379+ exists ( DataFlowType nt | nt = node .getDataFlowType ( ) |
3380+ if typeStrongerThan ( nt , t0 ) then t = nt else ( compatibleTypes ( nt , t0 ) and t = t0 )
3381+ )
3382+ else t = t0
3383+ )
3384+ )
3385+ }
3386+
33353387 /**
33363388 * Holds if data may flow from `mid` to `node`. The last step in or out of
33373389 * a callable is recorded by `cc`.
33383390 */
33393391 pragma [ assume_small_delta]
33403392 pragma [ nomagic]
3341- private predicate pathStep (
3393+ private predicate pathStep0 (
33423394 PathNodeMid mid , NodeEx node , FlowState state , CallContext cc , SummaryCtx sc , DataFlowType t ,
33433395 AccessPath ap
33443396 ) {
0 commit comments