@@ -102,6 +102,15 @@ module LocalFlow {
102102 or
103103 nodeFrom .asExpr ( ) = nodeTo .asStmt ( ) .( CfgNodes:: StmtNodes:: CmdExprCfgNode ) .getExpr ( )
104104 or
105+ exists (
106+ CfgNodes:: ExprNodes:: ArrayExprCfgNode arrayExpr , EscapeContainer:: EscapeContainer container
107+ |
108+ nodeTo .asExpr ( ) = arrayExpr and
109+ container = arrayExpr .getStmtBlock ( ) .getAstNode ( ) and
110+ nodeFrom .( AstNode ) .getCfgNode ( ) = container .getAnEscapingElement ( ) and
111+ not container .mayBeMultiReturned ( _)
112+ )
113+ or
105114 nodeFrom .( AstNode ) .getCfgNode ( ) = nodeTo .( PreReturNodeImpl ) .getReturnedNode ( )
106115 or
107116 exists ( CfgNode cfgNode |
@@ -550,100 +559,45 @@ abstract class ReturnNode extends Node {
550559 abstract ReturnKind getKind ( ) ;
551560}
552561
553- private module ReturnNodes {
554- /** An AST element that may produce return values when evaluated. */
555- abstract private class ReturnContainer extends Ast {
556- /**
557- * Gets a direct node that will may be returned when evaluating this node.
558- */
559- CfgNode getANode ( ) { none ( ) }
560-
561- /** Gets a child that may produce more nodes that may be returned. */
562- abstract ReturnContainer getAChild ( ) ;
563-
564- /**
565- * Gets a (possibly transitive) node that may be returned when evaluating
566- * this node.
567- */
568- final CfgNode getAReturnedNode ( ) {
569- result = this .getANode ( )
562+ private module EscapeContainer {
563+ private import semmle.code.powershell.internal.AstEscape:: Private
564+
565+ private module ReturnContainerInterpreter implements InterpretAstInputSig {
566+ class T = CfgNodes:: AstCfgNode ;
567+
568+ T interpret ( Ast a ) {
569+ result .( CfgNodes:: ExprCfgNode ) .getExpr ( ) = a
570570 or
571- result = this . getAChild ( ) . getAReturnedNode ( )
571+ result . ( CfgNodes :: StmtCfgNode ) . getStmt ( ) = a . ( Cmd )
572572 }
573+ }
573574
575+ class EscapeContainer extends AstEscape< ReturnContainerInterpreter > :: Element {
574576 /** Holds if `n` may be returned multiples times. */
575577 predicate mayBeMultiReturned ( CfgNode n ) {
576578 n = this .getANode ( ) and
577579 n .getASuccessor + ( ) = n
578580 or
579- this .getAChild ( ) .mayBeMultiReturned ( n )
580- }
581- }
582-
583- class ScriptBlockReturnContainer extends ReturnContainer , ScriptBlock {
584- final override ReturnContainer getAChild ( ) { result = this .getEndBlock ( ) }
585- }
586-
587- class NamedBlockReturnContainer extends ReturnContainer , NamedBlock {
588- final override ReturnContainer getAChild ( ) { result = this .getAStmt ( ) }
589- }
590-
591- class CmdExprReturnContainer extends ReturnContainer , CmdExpr {
592- final override CfgNodes:: ExprCfgNode getANode ( ) { result .getExpr ( ) = this .getExpr ( ) }
593-
594- final override ReturnContainer getAChild ( ) { none ( ) }
595- }
596-
597- class LoopStmtReturnContainer extends ReturnContainer , LoopStmt {
598- final override ReturnContainer getAChild ( ) { result = this .getBody ( ) }
599- }
600-
601- class StmtBlockReturnConainer extends ReturnContainer , StmtBlock {
602- final override ReturnContainer getAChild ( ) { result = this .getAStmt ( ) }
603- }
604-
605- class TryStmtReturnContainer extends ReturnContainer , TryStmt {
606- final override ReturnContainer getAChild ( ) {
607- result = this .getBody ( ) or result = this .getACatchClause ( ) or result = this .getFinally ( )
581+ this .getAChild ( ) .( EscapeContainer ) .mayBeMultiReturned ( n )
608582 }
609583 }
584+ }
610585
611- class ReturnStmtReturnContainer extends ReturnContainer , ReturnStmt {
612- final override ReturnContainer getAChild ( ) { result = this .getPipeline ( ) }
613- }
614-
615- class CatchClausReturnContainer extends ReturnContainer , CatchClause {
616- final override ReturnContainer getAChild ( ) { result = this .getBody ( ) }
617- }
618-
619- class SwitchStmtReturnContainer extends ReturnContainer , SwitchStmt {
620- final override ReturnContainer getAChild ( ) { result = this .getACase ( ) }
621- }
622-
623- class CmdBaseReturnContainer extends ReturnContainer , CmdExpr {
624- final override CfgNodes:: ExprCfgNode getANode ( ) { result .getExpr ( ) = this .getExpr ( ) }
625-
626- final override ReturnContainer getAChild ( ) { none ( ) }
627- }
628-
629- class CmdReturnContainer extends ReturnContainer , Cmd {
630- final override CfgNodes:: StmtCfgNode getANode ( ) { result .getStmt ( ) = this }
631-
632- final override ReturnContainer getAChild ( ) { none ( ) }
633- }
586+ private module ReturnNodes {
587+ private import EscapeContainer
634588
635- private predicate isReturnedImpl ( CfgNodes:: AstCfgNode n , ReturnContainer container ) {
589+ private predicate isReturnedImpl ( CfgNodes:: AstCfgNode n , EscapeContainer container ) {
636590 container = n .getScope ( ) and
637- n = container .getAReturnedNode ( )
591+ n = container .getAnEscapingElement ( )
638592 }
639593
640594 /**
641595 * Holds if `n` may be returned, and there are possibly
642596 * more than one return value from the function.
643597 */
644598 predicate isMultiReturned ( CfgNodes:: AstCfgNode n ) {
645- exists ( ReturnContainer container | isReturnedImpl ( n , container ) |
646- strictcount ( container .getAReturnedNode ( ) ) > 1
599+ exists ( EscapeContainer container | isReturnedImpl ( n , container ) |
600+ strictcount ( container .getAnEscapingElement ( ) ) > 1
647601 or
648602 container .mayBeMultiReturned ( n )
649603 )
@@ -722,6 +676,15 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
722676 index = ec .getIndex ( ) .asInt ( )
723677 )
724678 or
679+ exists (
680+ CfgNodes:: ExprNodes:: ArrayExprCfgNode arrayExpr , EscapeContainer:: EscapeContainer container
681+ |
682+ node2 .asExpr ( ) = arrayExpr and
683+ container = arrayExpr .getStmtBlock ( ) .getAstNode ( ) and
684+ node1 .( AstNode ) .getCfgNode ( ) = container .getAnEscapingElement ( ) and
685+ container .mayBeMultiReturned ( _)
686+ )
687+ or
725688 c .isAnyElement ( ) and
726689 exists ( CfgNode cfgNode |
727690 node1 = TPreReturnNodeImpl ( cfgNode , false ) and
0 commit comments