@@ -12,6 +12,65 @@ private import codeql.rust.controlflow.ControlFlowGraph
1212private import codeql.rust.controlflow.CfgNodes
1313private import codeql.rust.dataflow.Ssa
1414
15+ private newtype TReturnKind = TNormalReturnKind ( )
16+
17+ /**
18+ * A return kind. A return kind describes how a value can be returned from a
19+ * callable.
20+ *
21+ * The only return kind is a "normal" return from a `return` statement or an
22+ * expression body.
23+ */
24+ final class ReturnKind extends TNormalReturnKind {
25+ string toString ( ) { result = "return" }
26+ }
27+
28+ /**
29+ * A callable. This includes callables from source code, as well as callables
30+ * defined in library code.
31+ */
32+ final class DataFlowCallable extends TDataFlowCallable {
33+ /**
34+ * Gets the underlying CFG scope, if any.
35+ */
36+ CfgScope asCfgScope ( ) { this = TCfgScope ( result ) }
37+
38+ /** Gets a textual representation of this callable. */
39+ string toString ( ) { result = this .asCfgScope ( ) .toString ( ) }
40+
41+ /** Gets the location of this callable. */
42+ Location getLocation ( ) { result = this .asCfgScope ( ) .getLocation ( ) }
43+ }
44+
45+ abstract class DataFlowCall extends TDataFlowCall {
46+ /** Gets the enclosing callable. */
47+ abstract DataFlowCallable getEnclosingCallable ( ) ;
48+
49+ /** Gets the underlying source code call, if any. */
50+ abstract CallCfgNode asCall ( ) ;
51+
52+ /** Gets a textual representation of this call. */
53+ abstract string toString ( ) ;
54+
55+ /** Gets the location of this call. */
56+ abstract Location getLocation ( ) ;
57+ }
58+
59+ final class NormalCall extends DataFlowCall , TNormalCall {
60+ private CallCfgNode c ;
61+
62+ NormalCall ( ) { this = TNormalCall ( c ) }
63+
64+ /** Gets the underlying call in the CFG, if any. */
65+ override CallCfgNode asCall ( ) { result = c }
66+
67+ override DataFlowCallable getEnclosingCallable ( ) { none ( ) }
68+
69+ override string toString ( ) { result = c .toString ( ) }
70+
71+ override Location getLocation ( ) { result = c .getLocation ( ) }
72+ }
73+
1574module Node {
1675 /**
1776 * An element, viewed as a node in a data flow graph. Either an expression
@@ -29,6 +88,12 @@ module Node {
2988 */
3089 Expr asExpr ( ) { none ( ) }
3190
91+ /** Gets the enclosing callable. */
92+ DataFlowCallable getEnclosingCallable ( ) { result = TCfgScope ( this .getCfgScope ( ) ) }
93+
94+ /** Do not call: use `getEnclosingCallable()` instead. */
95+ abstract CfgScope getCfgScope ( ) ;
96+
3297 /**
3398 * Gets the control flow node that corresponds to this data flow node.
3499 */
@@ -49,6 +114,8 @@ module Node {
49114 final class NaNode extends Node {
50115 NaNode ( ) { none ( ) }
51116
117+ override CfgScope getCfgScope ( ) { none ( ) }
118+
52119 override string toString ( ) { result = "N/A" }
53120
54121 override Location getLocation ( ) { none ( ) }
@@ -62,11 +129,13 @@ module Node {
62129 * to multiple `ExprNode`s, just like it may correspond to multiple
63130 * `ControlFlow::Node`s.
64131 */
65- final class ExprNode extends Node , TExprNode {
132+ class ExprNode extends Node , TExprNode {
66133 ExprCfgNode n ;
67134
68135 ExprNode ( ) { this = TExprNode ( n ) }
69136
137+ override CfgScope getCfgScope ( ) { result = this .asExpr ( ) .getEnclosingCallable ( ) }
138+
70139 override Location getLocation ( ) { result = n .getExpr ( ) .getLocation ( ) }
71140
72141 override string toString ( ) { result = n .getExpr ( ) .toString ( ) }
@@ -85,6 +154,8 @@ module Node {
85154
86155 ParameterNode ( ) { this = TParameterNode ( parameter ) }
87156
157+ override CfgScope getCfgScope ( ) { result = parameter .getEnclosingCallable ( ) }
158+
88159 override Location getLocation ( ) { result = parameter .getLocation ( ) }
89160
90161 override string toString ( ) { result = parameter .toString ( ) }
@@ -105,6 +176,8 @@ module Node {
105176 def = node .getDefinitionExt ( )
106177 }
107178
179+ override CfgScope getCfgScope ( ) { result = def .getBasicBlock ( ) .getScope ( ) }
180+
108181 SsaImpl:: DefinitionExt getDefinitionExt ( ) { result = def }
109182
110183 /** Holds if this node should be hidden from path explanations. */
@@ -115,11 +188,25 @@ module Node {
115188 override string toString ( ) { result = node .toString ( ) }
116189 }
117190
118- final class ReturnNode extends NaNode {
119- RustDataFlow:: ReturnKind getKind ( ) { none ( ) }
191+ /** A data flow node that represents a value returned by a callable. */
192+ final class ReturnNode extends ExprNode {
193+ ReturnNode ( ) { this .getCfgNode ( ) .getASuccessor ( ) instanceof ExitCfgNode }
194+
195+ ReturnKind getKind ( ) { any ( ) }
196+ }
197+
198+ /** A data-flow node that represents the output of a call. */
199+ abstract class OutNode extends Node , ExprNode {
200+ /** Gets the underlying call for this node. */
201+ abstract DataFlowCall getCall ( ) ;
120202 }
121203
122- final class OutNode = NaNode ;
204+ final private class ExprOutNode extends OutNode {
205+ ExprOutNode ( ) { this .asExpr ( ) instanceof CallExpr }
206+
207+ /** Gets the underlying call CFG node that includes this out node. */
208+ override DataFlowCall getCall ( ) { result .( NormalCall ) .asCall ( ) = this .getCfgNode ( ) }
209+ }
123210
124211 /**
125212 * A node associated with an object after an operation that might have
@@ -198,6 +285,12 @@ module LocalFlow {
198285 }
199286}
200287
288+ private class DataFlowCallableAlias = DataFlowCallable ;
289+
290+ private class ReturnKindAlias = ReturnKind ;
291+
292+ private class DataFlowCallAlias = DataFlowCall ;
293+
201294module RustDataFlow implements InputSig< Location > {
202295 /**
203296 * An element, viewed as a node in a data flow graph. Either an expression
@@ -221,7 +314,7 @@ module RustDataFlow implements InputSig<Location> {
221314
222315 predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) { none ( ) }
223316
224- DataFlowCallable nodeGetEnclosingCallable ( Node node ) { none ( ) }
317+ DataFlowCallable nodeGetEnclosingCallable ( Node node ) { result = node . getEnclosingCallable ( ) }
225318
226319 DataFlowType getNodeType ( Node node ) { any ( ) }
227320
@@ -232,26 +325,22 @@ module RustDataFlow implements InputSig<Location> {
232325 /** Gets the node corresponding to `e`. */
233326 Node exprNode ( DataFlowExpr e ) { result .getCfgNode ( ) = e }
234327
235- final class DataFlowCall extends TNormalCall {
236- private CallExpr c ;
237-
238- DataFlowCall ( ) { this = TNormalCall ( c ) }
239-
240- DataFlowCallable getEnclosingCallable ( ) { none ( ) }
241-
242- string toString ( ) { result = c .toString ( ) }
243-
244- Location getLocation ( ) { result = c .getLocation ( ) }
245- }
328+ final class DataFlowCall = DataFlowCallAlias ;
246329
247- final class DataFlowCallable = CfgScope ;
330+ final class DataFlowCallable = DataFlowCallableAlias ;
248331
249- final class ReturnKind = Void ;
332+ final class ReturnKind = ReturnKindAlias ;
250333
251334 /** Gets a viable implementation of the target of the given `Call`. */
252335 DataFlowCallable viableCallable ( DataFlowCall c ) { none ( ) }
253336
254- OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) { none ( ) }
337+ /**
338+ * Gets a node that can read the value returned from `call` with return kind
339+ * `kind`.
340+ */
341+ OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) {
342+ call = result .getCall ( ) and exists ( kind )
343+ }
255344
256345 // NOTE: For now we use the type `Unit` and do not benefit from type
257346 // information in the data flow analysis.
@@ -400,7 +489,7 @@ private module Cached {
400489 TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
401490
402491 cached
403- newtype TDataFlowCall = TNormalCall ( CallExpr c )
492+ newtype TDataFlowCall = TNormalCall ( CallCfgNode c )
404493
405494 cached
406495 newtype TOptionalContentSet =
@@ -410,6 +499,9 @@ private module Cached {
410499 cached
411500 class TContentSet = TAnyElementContent or TAnyContent ;
412501
502+ cached
503+ newtype TDataFlowCallable = TCfgScope ( CfgScope scope )
504+
413505 /** This is the local flow predicate that is exposed. */
414506 cached
415507 predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
0 commit comments