@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
1135
1135
DataFlowCall call , ArgNodeEx arg , ParamNodeEx p , boolean allowsFieldFlow
1136
1136
) ;
1137
1137
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 ) ;
1140
1140
1141
1141
bindingset [ typ, contentType]
1142
1142
predicate typecheckStore ( Typ typ , DataFlowType contentType ) ;
@@ -1199,9 +1199,20 @@ module Impl<FullStateConfigSig Config> {
1199
1199
NodeEx node , FlowState state , Cc cc , ParamNodeOption summaryCtx , TypOption argT ,
1200
1200
ApOption argAp , Typ t , Ap ap , ApApprox apa
1201
1201
) {
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
1203
1210
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
1205
1216
}
1206
1217
1207
1218
pragma [ assume_small_delta]
@@ -1331,6 +1342,11 @@ module Impl<FullStateConfigSig Config> {
1331
1342
private predicate fwdFlowConsCand ( Typ t2 , Ap cons , Content c , Typ t1 , Ap tail ) {
1332
1343
fwdFlowStore ( _, t1 , tail , c , t2 , _, _, _, _, _, _) and
1333
1344
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
+ )
1334
1350
}
1335
1351
1336
1352
pragma [ nomagic]
@@ -1955,10 +1971,10 @@ module Impl<FullStateConfigSig Config> {
1955
1971
)
1956
1972
}
1957
1973
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 ) {
1960
1976
PrevStage:: revFlowState ( state ) and
1961
- exists ( t ) and
1977
+ t0 = t and
1962
1978
exists ( ap ) and
1963
1979
not stateBarrier ( node , state ) and
1964
1980
(
@@ -2210,10 +2226,16 @@ module Impl<FullStateConfigSig Config> {
2210
2226
)
2211
2227
}
2212
2228
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 ) {
2215
2231
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
2217
2239
(
2218
2240
notExpectsContent ( node )
2219
2241
or
@@ -2325,11 +2347,18 @@ module Impl<FullStateConfigSig Config> {
2325
2347
)
2326
2348
}
2327
2349
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 ) {
2330
2352
exists ( state ) and
2331
2353
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
2333
2362
(
2334
2363
notExpectsContent ( node )
2335
2364
or
@@ -2601,9 +2630,16 @@ module Impl<FullStateConfigSig Config> {
2601
2630
)
2602
2631
}
2603
2632
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
2607
2643
exists ( state ) and
2608
2644
exists ( ap )
2609
2645
}
@@ -2812,9 +2848,7 @@ module Impl<FullStateConfigSig Config> {
2812
2848
ap = TAccessPathNil ( )
2813
2849
or
2814
2850
// ... 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 )
2818
2852
} or
2819
2853
TPathNodeSink ( NodeEx node , FlowState state ) {
2820
2854
exists ( PathNodeMid sink |
@@ -3332,13 +3366,31 @@ module Impl<FullStateConfigSig Config> {
3332
3366
ap = mid .getAp ( )
3333
3367
}
3334
3368
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
+
3335
3387
/**
3336
3388
* Holds if data may flow from `mid` to `node`. The last step in or out of
3337
3389
* a callable is recorded by `cc`.
3338
3390
*/
3339
3391
pragma [ assume_small_delta]
3340
3392
pragma [ nomagic]
3341
- private predicate pathStep (
3393
+ private predicate pathStep0 (
3342
3394
PathNodeMid mid , NodeEx node , FlowState state , CallContext cc , SummaryCtx sc , DataFlowType t ,
3343
3395
AccessPath ap
3344
3396
) {
0 commit comments