@@ -166,9 +166,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
166
166
167
167
private newtype TNodeEx =
168
168
TNodeNormal ( Node n ) or
169
- TNodeImplicitRead ( Node n , boolean hasRead ) {
170
- Config:: allowImplicitRead ( n , _) and hasRead = [ false , true ]
171
- } or
169
+ TNodeImplicitRead ( Node n ) { Config:: allowImplicitRead ( n , _) } or
172
170
TParamReturnNode ( ParameterNode p , SndLevelScopeOption scope ) {
173
171
paramReturnNode ( _, p , scope , _)
174
172
}
@@ -177,25 +175,23 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
177
175
string toString ( ) {
178
176
result = this .asNode ( ) .toString ( )
179
177
or
180
- exists ( Node n | this .isImplicitReadNode ( n , _ ) | result = n .toString ( ) + " [Ext]" )
178
+ exists ( Node n | this .isImplicitReadNode ( n ) | result = n .toString ( ) + " [Ext]" )
181
179
or
182
180
result = this .asParamReturnNode ( ) .toString ( ) + " [Return]"
183
181
}
184
182
185
183
Node asNode ( ) { this = TNodeNormal ( result ) }
186
184
187
185
/** Gets the corresponding Node if this is a normal node or its post-implicit read node. */
188
- Node asNodeOrImplicitRead ( ) {
189
- this = TNodeNormal ( result ) or this = TNodeImplicitRead ( result , true )
190
- }
186
+ Node asNodeOrImplicitRead ( ) { this = TNodeNormal ( result ) or this = TNodeImplicitRead ( result ) }
191
187
192
- predicate isImplicitReadNode ( Node n , boolean hasRead ) { this = TNodeImplicitRead ( n , hasRead ) }
188
+ predicate isImplicitReadNode ( Node n ) { this = TNodeImplicitRead ( n ) }
193
189
194
190
ParameterNode asParamReturnNode ( ) { this = TParamReturnNode ( result , _) }
195
191
196
192
Node projectToNode ( ) {
197
193
this = TNodeNormal ( result ) or
198
- this = TNodeImplicitRead ( result , _ ) or
194
+ this = TNodeImplicitRead ( result ) or
199
195
this = TParamReturnNode ( result , _)
200
196
}
201
197
@@ -439,13 +435,6 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
439
435
stepFilter ( node1 , node2 )
440
436
)
441
437
or
442
- exists ( Node n |
443
- node1 .asNode ( ) = n and
444
- node2 .isImplicitReadNode ( n , false ) and
445
- not fullBarrier ( node1 ) and
446
- model = ""
447
- )
448
- or
449
438
exists ( Node n1 , Node n2 , SndLevelScopeOption scope |
450
439
node1 .asNode ( ) = n1 and
451
440
node2 = TParamReturnNode ( n2 , scope ) and
@@ -524,9 +513,13 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
524
513
stepFilter ( node1 , node2 )
525
514
or
526
515
exists ( Node n |
527
- node2 .isImplicitReadNode ( n , true ) and
528
- node1 .isImplicitReadNode ( n , _) and
516
+ node2 .isImplicitReadNode ( n ) and
529
517
Config:: allowImplicitRead ( n , c )
518
+ |
519
+ node1 .asNode ( ) = n and
520
+ not fullBarrier ( node1 )
521
+ or
522
+ node1 .isImplicitReadNode ( n )
530
523
)
531
524
}
532
525
@@ -802,7 +795,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
802
795
}
803
796
804
797
additional predicate sinkNode ( NodeEx node , FlowState state ) {
805
- fwdFlow ( node ) and
798
+ fwdFlow ( pragma [ only_bind_into ] ( node ) ) and
806
799
fwdFlowState ( state ) and
807
800
isRelevantSink ( node .asNodeOrImplicitRead ( ) )
808
801
or
@@ -2910,14 +2903,50 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
2910
2903
2911
2904
abstract PathNodeImpl getASuccessorImpl ( string label ) ;
2912
2905
2906
+ pragma [ nomagic]
2907
+ PathNodeImpl getAnImplicitReadSuccessorAtSink ( string label ) {
2908
+ exists ( PathNodeMid readTarget |
2909
+ result = this .getASuccessorImpl ( label ) and
2910
+ localStep ( this , readTarget , _) and
2911
+ readTarget .getNodeEx ( ) .isImplicitReadNode ( _)
2912
+ |
2913
+ // last implicit read, leaving the access path empty
2914
+ result = readTarget .projectToSink ( _)
2915
+ or
2916
+ // implicit read, leaving the access path non-empty
2917
+ exists ( result .getAnImplicitReadSuccessorAtSink ( _) ) and
2918
+ result = readTarget
2919
+ )
2920
+ }
2921
+
2913
2922
private PathNodeImpl getASuccessorIfHidden ( string label ) {
2914
2923
this .isHidden ( ) and
2915
2924
result = this .getASuccessorImpl ( label )
2925
+ or
2926
+ result = this .getAnImplicitReadSuccessorAtSink ( label )
2916
2927
}
2917
2928
2918
2929
private PathNodeImpl getASuccessorFromNonHidden ( string label ) {
2919
2930
result = this .getASuccessorImpl ( label ) and
2920
- not this .isHidden ( )
2931
+ not this .isHidden ( ) and
2932
+ // In cases like
2933
+ //
2934
+ // ```
2935
+ // x.Field = taint;
2936
+ // Sink(x);
2937
+ // ```
2938
+ //
2939
+ // we only want the direct edge
2940
+ //
2941
+ // `[post update] x [Field]` -> `x`
2942
+ //
2943
+ // and not the two edges
2944
+ //
2945
+ // `[post update] x [Field]` -> `x [Field]`
2946
+ // `x [Field]` -> `x`
2947
+ //
2948
+ // which the restriction below ensures.
2949
+ not result = this .getAnImplicitReadSuccessorAtSink ( label )
2921
2950
or
2922
2951
exists ( string l1 , string l2 |
2923
2952
result = this .getASuccessorFromNonHidden ( l1 ) .getASuccessorIfHidden ( l2 ) and
@@ -3391,6 +3420,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
3391
3420
private predicate localStepFromHidden ( PathNodeImpl n1 , PathNodeImpl n2 ) {
3392
3421
n2 = localStep ( n1 ) and
3393
3422
n1 .isHidden ( )
3423
+ or
3424
+ n2 = n1 .getAnImplicitReadSuccessorAtSink ( _)
3394
3425
}
3395
3426
3396
3427
bindingset [ par, ret]
0 commit comments