11private import swift
22private import DataFlowPublic
33private import DataFlowDispatch
4+ private import codeql.swift.controlflow.ControlFlowGraph
45private import codeql.swift.controlflow.CfgNodes
56private import codeql.swift.dataflow.Ssa
67private import codeql.swift.controlflow.BasicBlocks
@@ -20,7 +21,7 @@ predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos)
2021}
2122
2223abstract class NodeImpl extends Node {
23- DataFlowCallable getEnclosingCallable ( ) { none ( ) }
24+ abstract DataFlowCallable getEnclosingCallable ( ) ;
2425
2526 /** Do not call: use `getLocation()` instead. */
2627 abstract Location getLocationImpl ( ) ;
@@ -60,7 +61,21 @@ private module Cached {
6061 cached
6162 newtype TNode =
6263 TExprNode ( ExprCfgNode e ) or
63- TSsaDefinitionNode ( Ssa:: Definition def )
64+ TSsaDefinitionNode ( Ssa:: Definition def ) or
65+ TInoutReturnNode ( ParamDecl param ) { param .isInout ( ) } or
66+ TInOutUpdateNode ( ParamDecl param , CallExpr call ) {
67+ param .isInout ( ) and
68+ call .getStaticTarget ( ) = param .getDeclaringFunction ( )
69+ }
70+
71+ private predicate localSsaFlowStepUseUse ( Ssa:: Definition def , Node nodeFrom , Node nodeTo ) {
72+ def .adjacentReadPair ( nodeFrom .getCfgNode ( ) , nodeTo .getCfgNode ( ) ) and
73+ (
74+ nodeTo instanceof InoutReturnNode
75+ implies
76+ nodeTo .( InoutReturnNode ) .getParameter ( ) = def .getSourceVariable ( )
77+ )
78+ }
6479
6580 private predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
6681 exists ( Ssa:: Definition def |
@@ -70,14 +85,34 @@ private module Cached {
7085 or
7186 // step from def to first read
7287 nodeFrom .asDefinition ( ) = def and
73- nodeTo .getCfgNode ( ) = def .getAFirstRead ( )
88+ nodeTo .getCfgNode ( ) = def .getAFirstRead ( ) and
89+ (
90+ nodeTo instanceof InoutReturnNode
91+ implies
92+ nodeTo .( InoutReturnNode ) .getParameter ( ) = def .getSourceVariable ( )
93+ )
7494 or
7595 // use-use flow
76- def . adjacentReadPair ( nodeFrom . getCfgNode ( ) , nodeTo . getCfgNode ( ) )
96+ localSsaFlowStepUseUse ( def , nodeFrom , nodeTo )
7797 or
98+ //localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
99+ //or
78100 // step from previous read to Phi node
79101 localFlowSsaInput ( nodeFrom , def , nodeTo .asDefinition ( ) )
80102 )
103+ or
104+ exists ( ParamReturnKind kind , ExprCfgNode arg |
105+ arg =
106+ nodeFrom
107+ .( InOutUpdateNode )
108+ .getCall ( kind )
109+ .getCfgNode ( )
110+ .( CallExprCfgNode )
111+ .getArgument ( kind .getIndex ( ) ) and
112+ nodeTo .asDefinition ( ) .( Ssa:: WriteDefinition ) .isInoutDef ( arg )
113+ )
114+ or
115+ nodeFrom .asExpr ( ) = nodeTo .asExpr ( ) .( InOutExpr ) .getSubExpr ( )
81116 }
82117
83118 /**
@@ -172,6 +207,31 @@ private module ReturnNodes {
172207
173208 override ReturnKind getKind ( ) { result instanceof NormalReturnKind }
174209 }
210+
211+ class InoutReturnNodeImpl extends ReturnNode , TInoutReturnNode , NodeImpl {
212+ ParamDecl param ;
213+ ControlFlowNode exit ;
214+
215+ InoutReturnNodeImpl ( ) {
216+ this = TInoutReturnNode ( param ) and
217+ exit instanceof ExitNode and
218+ exit .getScope ( ) = param .getDeclaringFunction ( )
219+ }
220+
221+ override ReturnKind getKind ( ) { result .( ParamReturnKind ) .getIndex ( ) = param .getIndex ( ) }
222+
223+ override ControlFlowNode getCfgNode ( ) { result = exit }
224+
225+ override DataFlowCallable getEnclosingCallable ( ) {
226+ result = TDataFlowFunc ( param .getDeclaringFunction ( ) )
227+ }
228+
229+ ParamDecl getParameter ( ) { result = param }
230+
231+ override Location getLocationImpl ( ) { result = exit .getLocation ( ) }
232+
233+ override string toStringImpl ( ) { result = param .toString ( ) + "[return]" }
234+ }
175235}
176236
177237import ReturnNodes
@@ -188,6 +248,26 @@ private module OutNodes {
188248 result = this and kind instanceof NormalReturnKind
189249 }
190250 }
251+
252+ class InOutUpdateNode extends OutNode , TInOutUpdateNode , NodeImpl {
253+ ParamDecl param ;
254+ CallExpr call ;
255+
256+ InOutUpdateNode ( ) { this = TInOutUpdateNode ( param , call ) }
257+
258+ override DataFlowCall getCall ( ReturnKind kind ) {
259+ result .asExpr ( ) = call and
260+ kind .( ParamReturnKind ) .getIndex ( ) = param .getIndex ( )
261+ }
262+
263+ override DataFlowCallable getEnclosingCallable ( ) {
264+ result = TDataFlowFunc ( this .getCall ( _) .getCfgNode ( ) .getScope ( ) )
265+ }
266+
267+ override Location getLocationImpl ( ) { result = call .getLocation ( ) }
268+
269+ override string toStringImpl ( ) { result = param .toString ( ) }
270+ }
191271}
192272
193273import OutNodes
0 commit comments