@@ -944,17 +944,35 @@ import ReturnNodes
944944
945945/** A data flow node that represents the output of a call. */
946946abstract class OutNode extends Node {
947- /** Gets the underlying call. */
947+ /** Gets the underlying call, where this node is a corresponding output of kind `kind` . */
948948 cached
949- abstract DataFlowCall getCall ( ) ;
949+ abstract DataFlowCall getCall ( ReturnKind kind ) ;
950950}
951951
952952private module OutNodes {
953+ private import semmle.code.csharp.frameworks.system.Collections
954+ private import semmle.code.csharp.frameworks.system.collections.Generic
955+
953956 private DataFlowCall csharpCall ( Expr e , ControlFlow:: Node cfn ) {
954957 e = any ( DispatchCall dc | result = TNonDelegateCall ( cfn , dc ) ) .getCall ( ) or
955958 result = TExplicitDelegateCall ( cfn , e )
956959 }
957960
961+ /** A valid return type for a method that uses `yield return`. */
962+ private class YieldReturnType extends Type {
963+ YieldReturnType ( ) {
964+ exists ( Type t | t = this .getSourceDeclaration ( ) |
965+ t instanceof SystemCollectionsIEnumerableInterface
966+ or
967+ t instanceof SystemCollectionsIEnumeratorInterface
968+ or
969+ t instanceof SystemCollectionsGenericIEnumerableTInterface
970+ or
971+ t instanceof SystemCollectionsGenericIEnumeratorInterface
972+ )
973+ }
974+ }
975+
958976 /**
959977 * A data flow node that reads a value returned directly by a callable,
960978 * either via a C# call or a CIL call.
@@ -969,8 +987,16 @@ private module OutNodes {
969987 )
970988 }
971989
972- override DataFlowCall getCall ( ) {
973- Stages:: DataFlowStage:: forceCachingInSameStage ( ) and result = call
990+ override DataFlowCall getCall ( ReturnKind kind ) {
991+ Stages:: DataFlowStage:: forceCachingInSameStage ( ) and
992+ result = call and
993+ (
994+ kind instanceof NormalReturnKind and
995+ not call .getExpr ( ) .getType ( ) instanceof VoidType
996+ or
997+ kind instanceof YieldReturnKind and
998+ call .getExpr ( ) .getType ( ) instanceof YieldReturnType
999+ )
9741000 }
9751001 }
9761002
@@ -995,21 +1021,30 @@ private module OutNodes {
9951021 )
9961022 }
9971023
998- override DataFlowCall getCall ( ) { result = call }
1024+ override DataFlowCall getCall ( ReturnKind kind ) {
1025+ result = call and
1026+ kind .( ImplicitCapturedReturnKind ) .getVariable ( ) = this
1027+ .getDefinition ( )
1028+ .getSourceVariable ( )
1029+ .getAssignable ( )
1030+ }
9991031 }
10001032
10011033 /**
10021034 * A data flow node that reads a value returned by a callable using an
10031035 * `out` or `ref` parameter.
10041036 */
10051037 class ParamOutNode extends OutNode , SsaDefinitionNode {
1006- ParamOutNode ( ) {
1007- this .getDefinition ( ) .( Ssa:: ExplicitDefinition ) .getADefinition ( ) instanceof
1008- AssignableDefinitions:: OutRefDefinition
1009- }
1038+ private AssignableDefinitions:: OutRefDefinition outRefDef ;
10101039
1011- override DataFlowCall getCall ( ) {
1012- result = csharpCall ( _, this .getDefinition ( ) .getControlFlowNode ( ) )
1040+ ParamOutNode ( ) { outRefDef = this .getDefinition ( ) .( Ssa:: ExplicitDefinition ) .getADefinition ( ) }
1041+
1042+ override DataFlowCall getCall ( ReturnKind kind ) {
1043+ result = csharpCall ( _, this .getDefinition ( ) .getControlFlowNode ( ) ) and
1044+ exists ( Parameter p |
1045+ p .getSourceDeclaration ( ) .getPosition ( ) = kind .( OutRefReturnKind ) .getPosition ( ) and
1046+ outRefDef .getTargetAccess ( ) = result .getExpr ( ) .( Call ) .getArgumentForParameter ( p )
1047+ )
10131048 }
10141049 }
10151050
@@ -1036,7 +1071,16 @@ private module OutNodes {
10361071
10371072 override ControlFlow:: Nodes:: ElementNode getControlFlowNode ( ) { result = cfn }
10381073
1039- override ImplicitDelegateDataFlowCall getCall ( ) { result .getNode ( ) = this }
1074+ override ImplicitDelegateDataFlowCall getCall ( ReturnKind kind ) {
1075+ result .getNode ( ) = this and
1076+ (
1077+ kind instanceof NormalReturnKind and
1078+ not result .getDelegateReturnType ( ) instanceof VoidType
1079+ or
1080+ kind instanceof YieldReturnKind and
1081+ result .getDelegateReturnType ( ) instanceof YieldReturnType
1082+ )
1083+ }
10401084
10411085 override Callable getEnclosingCallable ( ) { result = cfn .getEnclosingCallable ( ) }
10421086
0 commit comments