@@ -8,6 +8,7 @@ private import DataFlowDispatch
88private import SsaImpl as SsaImpl
99private import FlowSummaryImpl as FlowSummaryImpl
1010private import semmle.code.powershell.frameworks.data.ModelsAsData
11+ private import PipelineReturns as PipelineReturns
1112
1213/** Gets the callable in which this node occurs. */
1314DataFlowCallable nodeGetEnclosingCallable ( Node n ) { result = n .( NodeImpl ) .getEnclosingCallable ( ) }
@@ -87,6 +88,16 @@ module SsaFlow {
8788 }
8889}
8990
91+ private module ArrayExprFlow {
92+ private module Input implements PipelineReturns:: InputSig {
93+ predicate isSource ( CfgNodes:: AstCfgNode source ) {
94+ source = any ( CfgNodes:: ExprNodes:: ArrayExprCfgNode ae ) .getStmtBlock ( )
95+ }
96+ }
97+
98+ import PipelineReturns:: Make< Input >
99+ }
100+
90101/** Provides predicates related to local data flow. */
91102module LocalFlow {
92103 pragma [ nomagic]
@@ -184,8 +195,12 @@ private module Cached {
184195 n = any ( CfgNodes:: ExprNodes:: IndexExprCfgNode index ) .getBase ( )
185196 } or
186197 TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
187- TPreReturnNodeImpl ( CfgNodes:: AstCfgNode n , Boolean isArray ) { isMultiReturned ( n ) } or
188- TImplicitWrapNode ( CfgNodes:: AstCfgNode n , Boolean shouldWrap ) { isMultiReturned ( n ) } or
198+ TPreReturnNodeImpl ( CfgNodes:: ScriptBlockCfgNode scriptBlock , Boolean isArray ) {
199+ blockMayReturnMultipleValues ( scriptBlock )
200+ } or
201+ TImplicitWrapNode ( CfgNodes:: ScriptBlockCfgNode scriptBlock , Boolean shouldWrap ) {
202+ blockMayReturnMultipleValues ( scriptBlock )
203+ } or
189204 TReturnNodeImpl ( CfgScope scope ) or
190205 TProcessNode ( ProcessBlock process ) or
191206 TProcessPropertyByNameNode ( PipelineByPropertyNameIteratorVariable iter ) {
@@ -752,64 +767,41 @@ abstract class ReturnNode extends Node {
752767 abstract ReturnKind getKind ( ) ;
753768}
754769
755- private module EscapeContainer {
756- private import semmle.code.powershell.internal.AstEscape :: Private
770+ private class SummaryReturnNode extends FlowSummaryNode , ReturnNode {
771+ private ReturnKind rk ;
757772
758- private module ReturnContainerInterpreter implements InterpretAstInputSig {
759- class T = CfgNodes:: AstCfgNode ;
760-
761- T interpret ( Ast a ) { result .( CfgNodes:: ExprCfgNode ) .getExpr ( ) = a } // TODO: Recutse into expr-to-stmt conversions
762- }
763-
764- class EscapeContainer extends AstEscape< ReturnContainerInterpreter > :: Element {
765- /** Holds if `n` may be returned multiples times. */
766- predicate mayBeMultiReturned ( CfgNode n ) {
767- n = this .getANode ( ) and
768- n .getASuccessor + ( ) = n
769- or
770- this .getAChild ( ) .( EscapeContainer ) .mayBeMultiReturned ( n )
771- }
772- }
773+ SummaryReturnNode ( ) { FlowSummaryImpl:: Private:: summaryReturnNode ( this .getSummaryNode ( ) , rk ) }
773774
774- private class SummaryReturnNode extends FlowSummaryNode , ReturnNode {
775- private ReturnKind rk ;
776-
777- SummaryReturnNode ( ) { FlowSummaryImpl:: Private:: summaryReturnNode ( this .getSummaryNode ( ) , rk ) }
778-
779- override ReturnKind getKind ( ) { result = rk }
780- }
775+ override ReturnKind getKind ( ) { result = rk }
781776}
782777
783778private module ReturnNodes {
784- private import EscapeContainer
779+ private CfgNodes:: NamedBlockCfgNode getAReturnBlock ( CfgNodes:: ScriptBlockCfgNode sb ) {
780+ result = sb .getBeginBlock ( )
781+ or
782+ result = sb .getEndBlock ( )
783+ or
784+ result = sb .getProcessBlock ( )
785+ }
785786
786- private predicate isReturnedImpl ( CfgNodes:: AstCfgNode n , EscapeContainer container ) {
787- container = n .getScope ( ) and
788- n = container .getAnEscapingElement ( )
787+ private module CfgScopeReturn implements PipelineReturns:: InputSig {
788+ predicate isSource ( CfgNodes:: AstCfgNode source ) { source = getAReturnBlock ( _) }
789789 }
790790
791+ private module P = PipelineReturns:: Make< CfgScopeReturn > ;
792+
791793 /**
792794 * Holds if `n` may be returned, and there are possibly
793795 * more than one return value from the function.
794796 */
795- predicate isMultiReturned ( CfgNodes:: AstCfgNode n ) {
796- exists ( EscapeContainer container | isReturnedImpl ( n , container ) |
797- strictcount ( container .getAnEscapingElement ( ) ) > 1
798- or
799- container .mayBeMultiReturned ( n )
800- )
797+ predicate blockMayReturnMultipleValues ( CfgNodes:: ScriptBlockCfgNode scriptBlock ) {
798+ P:: mayReturnMultipleValues ( getAReturnBlock ( scriptBlock ) )
801799 }
802800
803801 /**
804802 * Holds if `n` may be returned.
805803 */
806- predicate isReturned ( CfgNodes:: AstCfgNode n ) { isReturnedImpl ( n , _) }
807-
808- /**
809- * Holds if `n` may be returned, and this is the only value that may be
810- * returned from the function.
811- */
812- predicate isUniqueReturned ( CfgNodes:: AstCfgNode n ) { isReturned ( n ) and not isMultiReturned ( n ) }
804+ predicate isReturned ( CfgNodes:: AstCfgNode n ) { n = P:: getAReturn ( _) }
813805
814806 class NormalReturnNode extends ReturnNode instanceof ReturnNodeImpl {
815807 final override NormalReturnKind getKind ( ) { any ( ) }
0 commit comments