@@ -166,9 +166,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
166166
167167 private newtype TNodeEx =
168168 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
172170 TParamReturnNode ( ParameterNode p , SndLevelScopeOption scope ) {
173171 paramReturnNode ( _, p , scope , _)
174172 }
@@ -177,25 +175,23 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
177175 string toString ( ) {
178176 result = this .asNode ( ) .toString ( )
179177 or
180- exists ( Node n | this .isImplicitReadNode ( n , _ ) | result = n .toString ( ) + " [Ext]" )
178+ exists ( Node n | this .isImplicitReadNode ( n ) | result = n .toString ( ) + " [Ext]" )
181179 or
182180 result = this .asParamReturnNode ( ) .toString ( ) + " [Return]"
183181 }
184182
185183 Node asNode ( ) { this = TNodeNormal ( result ) }
186184
187185 /** 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 ) }
191187
192- predicate isImplicitReadNode ( Node n , boolean hasRead ) { this = TNodeImplicitRead ( n , hasRead ) }
188+ predicate isImplicitReadNode ( Node n ) { this = TNodeImplicitRead ( n ) }
193189
194190 ParameterNode asParamReturnNode ( ) { this = TParamReturnNode ( result , _) }
195191
196192 Node projectToNode ( ) {
197193 this = TNodeNormal ( result ) or
198- this = TNodeImplicitRead ( result , _ ) or
194+ this = TNodeImplicitRead ( result ) or
199195 this = TParamReturnNode ( result , _)
200196 }
201197
@@ -439,13 +435,6 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
439435 stepFilter ( node1 , node2 )
440436 )
441437 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
449438 exists ( Node n1 , Node n2 , SndLevelScopeOption scope |
450439 node1 .asNode ( ) = n1 and
451440 node2 = TParamReturnNode ( n2 , scope ) and
@@ -524,9 +513,13 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
524513 stepFilter ( node1 , node2 )
525514 or
526515 exists ( Node n |
527- node2 .isImplicitReadNode ( n , true ) and
528- node1 .isImplicitReadNode ( n , _) and
516+ node2 .isImplicitReadNode ( n ) and
529517 Config:: allowImplicitRead ( n , c )
518+ |
519+ node1 .asNode ( ) = n and
520+ not fullBarrier ( node1 )
521+ or
522+ node1 .isImplicitReadNode ( n )
530523 )
531524 }
532525
@@ -802,7 +795,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
802795 }
803796
804797 additional predicate sinkNode ( NodeEx node , FlowState state ) {
805- fwdFlow ( node ) and
798+ fwdFlow ( pragma [ only_bind_into ] ( node ) ) and
806799 fwdFlowState ( state ) and
807800 isRelevantSink ( node .asNodeOrImplicitRead ( ) )
808801 or
@@ -2910,14 +2903,50 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
29102903
29112904 abstract PathNodeImpl getASuccessorImpl ( string label ) ;
29122905
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+
29132922 private PathNodeImpl getASuccessorIfHidden ( string label ) {
29142923 this .isHidden ( ) and
29152924 result = this .getASuccessorImpl ( label )
2925+ or
2926+ result = this .getAnImplicitReadSuccessorAtSink ( label )
29162927 }
29172928
29182929 private PathNodeImpl getASuccessorFromNonHidden ( string label ) {
29192930 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 )
29212950 or
29222951 exists ( string l1 , string l2 |
29232952 result = this .getASuccessorFromNonHidden ( l1 ) .getASuccessorIfHidden ( l2 ) and
@@ -3391,6 +3420,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
33913420 private predicate localStepFromHidden ( PathNodeImpl n1 , PathNodeImpl n2 ) {
33923421 n2 = localStep ( n1 ) and
33933422 n1 .isHidden ( )
3423+ or
3424+ n2 = n1 .getAnImplicitReadSuccessorAtSink ( _)
33943425 }
33953426
33963427 bindingset [ par, ret]
0 commit comments