@@ -850,6 +850,85 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
850850
851851 class SndLevelScopeOption = SndLevelScopeOption:: Option ;
852852
853+ final class NodeExImpl extends TNodeEx {
854+ string toString ( ) {
855+ result = this .asNode ( ) .toString ( )
856+ or
857+ exists ( Node n | this .isImplicitReadNode ( n ) | result = n .toString ( ) + " [Ext]" )
858+ or
859+ result = this .asParamReturnNode ( ) .toString ( ) + " [Return]"
860+ }
861+
862+ Node asNode ( ) { this = TNodeNormal ( result ) }
863+
864+ /** Gets the corresponding Node if this is a normal node or its post-implicit read node. */
865+ Node asNodeOrImplicitRead ( ) { this = TNodeNormal ( result ) or this = TNodeImplicitRead ( result ) }
866+
867+ predicate isImplicitReadNode ( Node n ) { this = TNodeImplicitRead ( n ) }
868+
869+ ParameterNode asParamReturnNode ( ) { this = TParamReturnNode ( result , _) }
870+
871+ Node projectToNode ( ) {
872+ this = TNodeNormal ( result ) or
873+ this = TNodeImplicitRead ( result ) or
874+ this = TParamReturnNode ( result , _)
875+ }
876+
877+ pragma [ nomagic]
878+ private DataFlowCallable getEnclosingCallable0 ( ) {
879+ nodeEnclosingCallable ( this .projectToNode ( ) , result )
880+ }
881+
882+ pragma [ inline]
883+ DataFlowCallable getEnclosingCallable ( ) {
884+ pragma [ only_bind_out ] ( this ) .getEnclosingCallable0 ( ) = pragma [ only_bind_into ] ( result )
885+ }
886+
887+ pragma [ nomagic]
888+ private DataFlowType getDataFlowType0 ( ) {
889+ nodeDataFlowType ( this .asNode ( ) , result )
890+ or
891+ nodeDataFlowType ( this .asParamReturnNode ( ) , result )
892+ }
893+
894+ pragma [ inline]
895+ DataFlowType getDataFlowType ( ) {
896+ pragma [ only_bind_out ] ( this ) .getDataFlowType0 ( ) = pragma [ only_bind_into ] ( result )
897+ }
898+
899+ Location getLocation ( ) { result = this .projectToNode ( ) .getLocation ( ) }
900+ }
901+
902+ final class ArgNodeExImpl extends NodeExImpl {
903+ ArgNodeExImpl ( ) { this .asNode ( ) instanceof ArgNode }
904+
905+ DataFlowCall getCall ( ) { this .asNode ( ) .( ArgNode ) .argumentOf ( result , _) }
906+ }
907+
908+ final class ParamNodeExImpl extends NodeExImpl {
909+ ParamNodeExImpl ( ) { this .asNode ( ) instanceof ParamNode }
910+
911+ predicate isParameterOf ( DataFlowCallable c , ParameterPosition pos ) {
912+ this .asNode ( ) .( ParamNode ) .isParameterOf ( c , pos )
913+ }
914+
915+ ParameterPosition getPosition ( ) { this .isParameterOf ( _, result ) }
916+ }
917+
918+ /**
919+ * A node from which flow can return to the caller. This is either a regular
920+ * `ReturnNode` or a synthesized node for flow out via a parameter.
921+ */
922+ final class RetNodeExImpl extends NodeExImpl {
923+ private ReturnPosition pos ;
924+
925+ RetNodeExImpl ( ) { pos = getReturnPositionEx ( this ) }
926+
927+ ReturnPosition getReturnPosition ( ) { result = pos }
928+
929+ ReturnKindExt getKind ( ) { result = pos .getKind ( ) }
930+ }
931+
853932 cached
854933 private module Cached {
855934 /**
@@ -927,11 +1006,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
9271006 )
9281007 }
9291008
930- cached
931- predicate valueReturnNode ( ReturnNode n , ReturnKindExt k ) { k = TValueReturn ( n .getKind ( ) ) }
932-
933- cached
934- predicate paramReturnNode (
1009+ pragma [ nomagic]
1010+ private predicate paramReturnNode (
9351011 PostUpdateNode n , ParamNode p , SndLevelScopeOption scope , ReturnKindExt k
9361012 ) {
9371013 exists ( ParameterPosition pos |
@@ -1541,6 +1617,20 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
15411617
15421618 class UnreachableSetOption = UnreachableSetOption:: Option ;
15431619
1620+ pragma [ nomagic]
1621+ private predicate hasValueReturnKindIn ( ReturnNode ret , ReturnKindExt kind , DataFlowCallable c ) {
1622+ c = getNodeEnclosingCallable ( ret ) and
1623+ kind = TValueReturn ( ret .getKind ( ) )
1624+ }
1625+
1626+ pragma [ nomagic]
1627+ private predicate hasParamReturnKindIn (
1628+ PostUpdateNode n , ParamNode p , ReturnKindExt kind , DataFlowCallable c
1629+ ) {
1630+ c = getNodeEnclosingCallable ( n ) and
1631+ paramReturnNode ( n , p , _, kind )
1632+ }
1633+
15441634 cached
15451635 newtype TReturnPosition =
15461636 TReturnPosition0 ( DataFlowCallable c , ReturnKindExt kind ) {
@@ -1549,6 +1639,22 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
15491639 hasParamReturnKindIn ( _, _, kind , c )
15501640 }
15511641
1642+ cached
1643+ ReturnPosition getValueReturnPosition ( ReturnNode ret ) {
1644+ exists ( ReturnKindExt kind , DataFlowCallable c |
1645+ hasValueReturnKindIn ( ret , kind , c ) and
1646+ result = TReturnPosition0 ( c , kind )
1647+ )
1648+ }
1649+
1650+ cached
1651+ ReturnPosition getParamReturnPosition ( PostUpdateNode n , ParamNode p ) {
1652+ exists ( ReturnKindExt kind , DataFlowCallable c |
1653+ hasParamReturnKindIn ( n , p , kind , c ) and
1654+ result = TReturnPosition0 ( c , kind )
1655+ )
1656+ }
1657+
15521658 cached
15531659 newtype TLocalFlowCallContext =
15541660 TAnyLocalCall ( ) or
@@ -1594,6 +1700,44 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
15941700 newtype TApproxAccessPathFrontOption =
15951701 TApproxAccessPathFrontNone ( ) or
15961702 TApproxAccessPathFrontSome ( ApproxAccessPathFront apf )
1703+
1704+ cached
1705+ newtype TNodeEx =
1706+ TNodeNormal ( Node n ) or
1707+ TNodeImplicitRead ( Node n ) or // will be restricted to nodes with actual implicit reads in `DataFlowImpl.qll`
1708+ TParamReturnNode ( ParameterNode p , SndLevelScopeOption scope ) {
1709+ paramReturnNode ( _, p , scope , _)
1710+ }
1711+
1712+ /**
1713+ * Holds if data can flow in one local step from `node1` to `node2`.
1714+ */
1715+ cached
1716+ predicate localFlowStepExImpl ( NodeExImpl node1 , NodeExImpl node2 , string model ) {
1717+ exists ( Node n1 , Node n2 |
1718+ node1 .asNode ( ) = n1 and
1719+ node2 .asNode ( ) = n2 and
1720+ simpleLocalFlowStepExt ( pragma [ only_bind_into ] ( n1 ) , pragma [ only_bind_into ] ( n2 ) , model )
1721+ )
1722+ or
1723+ exists ( Node n1 , Node n2 , SndLevelScopeOption scope |
1724+ node1 .asNode ( ) = n1 and
1725+ node2 = TParamReturnNode ( n2 , scope ) and
1726+ paramReturnNode ( pragma [ only_bind_into ] ( n1 ) , pragma [ only_bind_into ] ( n2 ) ,
1727+ pragma [ only_bind_into ] ( scope ) , _) and
1728+ model = ""
1729+ )
1730+ }
1731+
1732+ cached
1733+ ReturnPosition getReturnPositionEx ( NodeExImpl ret ) {
1734+ result = getValueReturnPosition ( ret .asNode ( ) )
1735+ or
1736+ exists ( ParamNode p |
1737+ ret = TParamReturnNode ( p , _) and
1738+ result = getParamReturnPosition ( _, p )
1739+ )
1740+ }
15971741 }
15981742
15991743 bindingset [ call, tgt]
@@ -2177,36 +2321,6 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
21772321 nodeDataFlowType ( pragma [ only_bind_out ] ( n ) , pragma [ only_bind_into ] ( result ) )
21782322 }
21792323
2180- pragma [ nomagic]
2181- private predicate hasValueReturnKindIn ( ReturnNode ret , ReturnKindExt kind , DataFlowCallable c ) {
2182- c = getNodeEnclosingCallable ( ret ) and
2183- valueReturnNode ( ret , kind )
2184- }
2185-
2186- pragma [ nomagic]
2187- private predicate hasParamReturnKindIn (
2188- PostUpdateNode n , ParamNode p , ReturnKindExt kind , DataFlowCallable c
2189- ) {
2190- c = getNodeEnclosingCallable ( n ) and
2191- paramReturnNode ( n , p , _, kind )
2192- }
2193-
2194- pragma [ nomagic]
2195- ReturnPosition getValueReturnPosition ( ReturnNode ret ) {
2196- exists ( ReturnKindExt kind , DataFlowCallable c |
2197- hasValueReturnKindIn ( ret , kind , c ) and
2198- result = TReturnPosition0 ( c , kind )
2199- )
2200- }
2201-
2202- pragma [ nomagic]
2203- ReturnPosition getParamReturnPosition ( PostUpdateNode n , ParamNode p ) {
2204- exists ( ReturnKindExt kind , DataFlowCallable c |
2205- hasParamReturnKindIn ( n , p , kind , c ) and
2206- result = TReturnPosition0 ( c , kind )
2207- )
2208- }
2209-
22102324 /** An optional Boolean value. */
22112325 class BooleanOption extends TBooleanOption {
22122326 string toString ( ) {
0 commit comments