@@ -14,6 +14,7 @@ private import codeql.rust.controlflow.ControlFlowGraph
1414private import codeql.rust.controlflow.CfgNodes
1515private import codeql.rust.dataflow.Ssa
1616private import codeql.rust.dataflow.FlowSummary
17+ private import codeql.rust.internal.TypeInference as TypeInference
1718private import Node as Node
1819private import DataFlowImpl
1920private import FlowSummaryImpl as FlowSummaryImpl
@@ -226,35 +227,53 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
226227 private Call call_ ;
227228 private RustDataFlow:: ArgumentPosition pos_ ;
228229
229- ExprArgumentNode ( ) { isArgumentForCall ( n , call_ , pos_ ) }
230+ ExprArgumentNode ( ) {
231+ isArgumentForCall ( n , call_ , pos_ ) and
232+ not TypeInference:: implicitDeref ( n ) and
233+ not TypeInference:: implicitBorrow ( n )
234+ }
230235
231236 override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
232237 call .asCall ( ) = call_ and pos = pos_
233238 }
234239}
235240
236241/**
237- * The receiver of a method call _after_ any implicit borrow or dereferencing
238- * has taken place .
242+ * A node that represents the value of an expression _after_ implicit dereferencing
243+ * or borrowing .
239244 */
240- final class ReceiverNode extends ArgumentNode , TReceiverNode {
241- private Call n ;
245+ class DerefBorrowNode extends Node , TDerefBorrowNode {
246+ AstNode n ;
247+ boolean isBorrow ;
242248
243- ReceiverNode ( ) { this = TReceiverNode ( n , false ) }
249+ DerefBorrowNode ( ) { this = TDerefBorrowNode ( n , isBorrow , false ) }
244250
245- Expr getReceiver ( ) { result = n . getReceiver ( ) }
251+ AstNode getNode ( ) { result = n }
246252
247- MethodCallExpr getMethodCall ( ) { result = n }
253+ predicate isBorrow ( ) { isBorrow = true }
248254
249- override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
250- call .asCall ( ) = n and pos = TSelfParameterPosition ( )
255+ override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
256+
257+ override Location getLocation ( ) { result = n .getLocation ( ) }
258+
259+ override string toString ( ) {
260+ if isBorrow = true then result = n + " [borrowed]" else result = n + " [dereferenced]"
251261 }
262+ }
252263
253- override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
264+ /**
265+ * A node that represents the value of an argument of a call _after_ implicit
266+ * dereferencing or borrowing.
267+ */
268+ final class DerefBorrowArgNode extends DerefBorrowNode , ArgumentNode {
269+ private DataFlowCall call_ ;
270+ private RustDataFlow:: ArgumentPosition pos_ ;
254271
255- override Location getLocation ( ) { result = this . getReceiver ( ) . getLocation ( ) }
272+ DerefBorrowArgNode ( ) { isArgumentForCall ( n , call_ . asCall ( ) , pos_ ) }
256273
257- override string toString ( ) { result = "receiver for " + this .getReceiver ( ) }
274+ override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
275+ call = call_ and pos = pos_
276+ }
258277}
259278
260279final class SummaryArgumentNode extends FlowSummaryNode , ArgumentNode {
@@ -329,15 +348,46 @@ abstract class OutNode extends Node {
329348}
330349
331350final private class ExprOutNode extends ExprNode , OutNode {
332- ExprOutNode ( ) { this .asExpr ( ) instanceof Call }
351+ ExprOutNode ( ) {
352+ exists ( Call call |
353+ call = this .asExpr ( ) and
354+ not call instanceof DerefExpr // Handled by `DerefOutNode`
355+ )
356+ }
333357
334- /** Gets the underlying call CFG node that includes this out node. */
358+ /** Gets the underlying call node that includes this out node. */
335359 override DataFlowCall getCall ( ReturnKind kind ) {
336360 result .asCall ( ) = n and
337361 kind = TNormalReturnKind ( )
338362 }
339363}
340364
365+ /**
366+ * A node that represents the value of a `*` expression _before_ implicit
367+ * dereferencing:
368+ *
369+ * `*v` equivalent to `*Deref::deref(&v)`, and this node represents the
370+ * `Deref::deref(&v)` part.
371+ */
372+ class DerefOutNode extends OutNode , TDerefOutNode {
373+ DerefExpr de ;
374+
375+ DerefOutNode ( ) { this = TDerefOutNode ( de , false ) }
376+
377+ DerefExpr getDerefExpr ( ) { result = de }
378+
379+ override CfgScope getCfgScope ( ) { result = de .getEnclosingCfgScope ( ) }
380+
381+ override DataFlowCall getCall ( ReturnKind kind ) {
382+ result .asCall ( ) = de and
383+ kind = TNormalReturnKind ( )
384+ }
385+
386+ override Location getLocation ( ) { result = de .getLocation ( ) }
387+
388+ override string toString ( ) { result = de .toString ( ) + " [pre-dereferenced]" }
389+ }
390+
341391final class SummaryOutNode extends FlowSummaryNode , OutNode {
342392 private DataFlowCall call ;
343393 private ReturnKind kind_ ;
@@ -402,16 +452,29 @@ final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
402452 override Location getLocation ( ) { result = e .getLocation ( ) }
403453}
404454
405- final class ReceiverPostUpdateNode extends PostUpdateNode , TReceiverNode {
406- private Call call ;
455+ final class DerefBorrowPostUpdateNode extends PostUpdateNode , TDerefBorrowNode {
456+ private Expr arg ;
457+ private boolean isBorrow ;
407458
408- ReceiverPostUpdateNode ( ) { this = TReceiverNode ( call , true ) }
459+ DerefBorrowPostUpdateNode ( ) { this = TDerefBorrowNode ( arg , isBorrow , true ) }
409460
410- override Node getPreUpdateNode ( ) { result = TReceiverNode ( call , false ) }
461+ override DerefBorrowNode getPreUpdateNode ( ) { result = TDerefBorrowNode ( arg , isBorrow , false ) }
411462
412- override CfgScope getCfgScope ( ) { result = call .getEnclosingCfgScope ( ) }
463+ override CfgScope getCfgScope ( ) { result = arg .getEnclosingCfgScope ( ) }
413464
414- override Location getLocation ( ) { result = call .getReceiver ( ) .getLocation ( ) }
465+ override Location getLocation ( ) { result = arg .getLocation ( ) }
466+ }
467+
468+ class DerefOutPostUpdateNode extends PostUpdateNode , TDerefOutNode {
469+ DerefExpr de ;
470+
471+ DerefOutPostUpdateNode ( ) { this = TDerefOutNode ( de , true ) }
472+
473+ override DerefOutNode getPreUpdateNode ( ) { result = TDerefOutNode ( de , false ) }
474+
475+ override CfgScope getCfgScope ( ) { result = de .getEnclosingCfgScope ( ) }
476+
477+ override Location getLocation ( ) { result = de .getLocation ( ) }
415478}
416479
417480final class SummaryPostUpdateNode extends FlowSummaryNode , PostUpdateNode {
@@ -467,19 +530,19 @@ newtype TNode =
467530 any ( IndexExpr i ) .getBase ( ) , //
468531 any ( FieldExpr access ) .getContainer ( ) , //
469532 any ( TryExpr try ) .getExpr ( ) , //
470- any ( PrefixExpr pe | pe .getOperatorName ( ) = "*" ) .getExpr ( ) , //
471533 any ( AwaitExpr a ) .getExpr ( ) , //
472- any ( MethodCallExpr mc ) .getReceiver ( ) , //
473534 getPostUpdateReverseStep ( any ( PostUpdateNode n ) .getPreUpdateNode ( ) .asExpr ( ) , _)
474535 ]
475536 )
476537 } or
477- TReceiverNode ( Call call , Boolean isPost ) {
478- call .hasEnclosingCfgScope ( ) and
479- call .receiverImplicitlyBorrowed ( ) and
480- // TODO: Handle index expressions as calls in data flow.
481- not call instanceof IndexExpr
538+ TDerefBorrowNode ( AstNode n , boolean borrow , Boolean isPost ) {
539+ TypeInference:: implicitDeref ( n ) and
540+ borrow = false
541+ or
542+ TypeInference:: implicitBorrow ( n ) and
543+ borrow = true
482544 } or
545+ TDerefOutNode ( DerefExpr de , Boolean isPost ) or
483546 TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node ) or
484547 TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) {
485548 forall ( AstNode n | n = sn .getSinkElement ( ) or n = sn .getSourceElement ( ) |
0 commit comments