@@ -12,6 +12,64 @@ 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+ abstract string toString ( ) ;
53+
54+ /** Gets the location of this call. */
55+ abstract Location getLocation ( ) ;
56+ }
57+
58+ final class NormalCall extends DataFlowCall , TNormalCall {
59+ private CallCfgNode c ;
60+
61+ NormalCall ( ) { this = TNormalCall ( c ) }
62+
63+ /** Gets the underlying call in the CFG, if any. */
64+ override CallCfgNode asCall ( ) { result = c }
65+
66+ override DataFlowCallable getEnclosingCallable ( ) { none ( ) }
67+
68+ override string toString ( ) { result = c .toString ( ) }
69+
70+ override Location getLocation ( ) { result = c .getLocation ( ) }
71+ }
72+
1573module Node {
1674 /**
1775 * An element, viewed as a node in a data flow graph. Either an expression
@@ -29,6 +87,12 @@ module Node {
2987 */
3088 Expr asExpr ( ) { none ( ) }
3189
90+ /** Gets the enclosing callable. */
91+ DataFlowCallable getEnclosingCallable ( ) { result = TCfgScope ( this .getCfgScope ( ) ) }
92+
93+ /** Do not call: use `getEnclosingCallable()` instead. */
94+ abstract CfgScope getCfgScope ( ) ;
95+
3296 /**
3397 * Gets the control flow node that corresponds to this data flow node.
3498 */
@@ -49,6 +113,8 @@ module Node {
49113 final class NaNode extends Node {
50114 NaNode ( ) { none ( ) }
51115
116+ override CfgScope getCfgScope ( ) { none ( ) }
117+
52118 override string toString ( ) { result = "N/A" }
53119
54120 override Location getLocation ( ) { none ( ) }
@@ -62,11 +128,13 @@ module Node {
62128 * to multiple `ExprNode`s, just like it may correspond to multiple
63129 * `ControlFlow::Node`s.
64130 */
65- final class ExprNode extends Node , TExprNode {
131+ class ExprNode extends Node , TExprNode {
66132 ExprCfgNode n ;
67133
68134 ExprNode ( ) { this = TExprNode ( n ) }
69135
136+ override CfgScope getCfgScope ( ) { result = this .asExpr ( ) .getEnclosingCallable ( ) }
137+
70138 override Location getLocation ( ) { result = n .getExpr ( ) .getLocation ( ) }
71139
72140 override string toString ( ) { result = n .getExpr ( ) .toString ( ) }
@@ -85,6 +153,8 @@ module Node {
85153
86154 ParameterNode ( ) { this = TParameterNode ( parameter ) }
87155
156+ override CfgScope getCfgScope ( ) { result = parameter .getEnclosingCallable ( ) }
157+
88158 override Location getLocation ( ) { result = parameter .getLocation ( ) }
89159
90160 override string toString ( ) { result = parameter .toString ( ) }
@@ -105,6 +175,8 @@ module Node {
105175 def = node .getDefinitionExt ( )
106176 }
107177
178+ override CfgScope getCfgScope ( ) { result = def .getBasicBlock ( ) .getScope ( ) }
179+
108180 SsaImpl:: DefinitionExt getDefinitionExt ( ) { result = def }
109181
110182 /** Holds if this node should be hidden from path explanations. */
@@ -115,11 +187,25 @@ module Node {
115187 override string toString ( ) { result = node .toString ( ) }
116188 }
117189
118- final class ReturnNode extends NaNode {
119- RustDataFlow:: ReturnKind getKind ( ) { none ( ) }
190+ /** A data flow node that represents a value returned by a callable. */
191+ final class ReturnNode extends ExprNode {
192+ ReturnNode ( ) { this .getCfgNode ( ) .getASuccessor ( ) instanceof ExitCfgNode }
193+
194+ ReturnKind getKind ( ) { any ( ) }
195+ }
196+
197+ /** A data-flow node that represents the output of a call. */
198+ abstract class OutNode extends Node , ExprNode {
199+ /** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
200+ abstract DataFlowCall getCall ( ) ;
120201 }
121202
122- final class OutNode = NaNode ;
203+ final private class ExprOutNode extends OutNode {
204+ ExprOutNode ( ) { this .asExpr ( ) instanceof CallExpr }
205+
206+ /** Gets the underlying call CFG node that includes this out node. */
207+ override DataFlowCall getCall ( ) { result .( NormalCall ) .asCall ( ) = this .getCfgNode ( ) }
208+ }
123209
124210 /**
125211 * A node associated with an object after an operation that might have
@@ -198,6 +284,12 @@ module LocalFlow {
198284 }
199285}
200286
287+ class DataFlowCallableAlias = DataFlowCallable ;
288+
289+ class ReturnKindAlias = ReturnKind ;
290+
291+ class DataFlowCallAlias = DataFlowCall ;
292+
201293module RustDataFlow implements InputSig< Location > {
202294 /**
203295 * An element, viewed as a node in a data flow graph. Either an expression
@@ -221,7 +313,7 @@ module RustDataFlow implements InputSig<Location> {
221313
222314 predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) { none ( ) }
223315
224- DataFlowCallable nodeGetEnclosingCallable ( Node node ) { none ( ) }
316+ DataFlowCallable nodeGetEnclosingCallable ( Node node ) { result = node . getEnclosingCallable ( ) }
225317
226318 DataFlowType getNodeType ( Node node ) { any ( ) }
227319
@@ -232,26 +324,22 @@ module RustDataFlow implements InputSig<Location> {
232324 /** Gets the node corresponding to `e`. */
233325 Node exprNode ( DataFlowExpr e ) { result .getCfgNode ( ) = e }
234326
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- }
327+ final class DataFlowCall = DataFlowCallAlias ;
246328
247- final class DataFlowCallable = CfgScope ;
329+ final class DataFlowCallable = DataFlowCallableAlias ;
248330
249- final class ReturnKind = Void ;
331+ final class ReturnKind = ReturnKindAlias ;
250332
251333 /** Gets a viable implementation of the target of the given `Call`. */
252334 DataFlowCallable viableCallable ( DataFlowCall c ) { none ( ) }
253335
254- OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) { none ( ) }
336+ /**
337+ * Gets a node that can read the value returned from `call` with return kind
338+ * `kind`.
339+ */
340+ OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) {
341+ call = result .getCall ( ) and exists ( kind )
342+ }
255343
256344 // NOTE: For now we use the type `Unit` and do not benefit from type
257345 // information in the data flow analysis.
@@ -400,7 +488,7 @@ private module Cached {
400488 TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
401489
402490 cached
403- newtype TDataFlowCall = TNormalCall ( CallExpr c )
491+ newtype TDataFlowCall = TNormalCall ( CallCfgNode c )
404492
405493 cached
406494 newtype TOptionalContentSet =
@@ -410,6 +498,9 @@ private module Cached {
410498 cached
411499 class TContentSet = TAnyElementContent or TAnyContent ;
412500
501+ cached
502+ newtype TDataFlowCallable = TCfgScope ( CfgScope scope )
503+
413504 /** This is the local flow predicate that is exposed. */
414505 cached
415506 predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
0 commit comments