@@ -15,6 +15,7 @@ private import codeql.rust.controlflow.CfgNodes
1515private import codeql.rust.dataflow.Ssa
1616private import codeql.rust.dataflow.FlowSummary
1717private import codeql.rust.internal.TypeInference as TypeInference
18+ private import codeql.rust.internal.typeinference.DerefChain
1819private import Node as Node
1920private import DataFlowImpl
2021private import FlowSummaryImpl as FlowSummaryImpl
@@ -229,8 +230,7 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
229230
230231 ExprArgumentNode ( ) {
231232 isArgumentForCall ( n , call_ , pos_ ) and
232- not TypeInference:: implicitDeref ( n ) and
233- not TypeInference:: implicitBorrow ( n , _)
233+ not TypeInference:: implicitDerefChainBorrow ( n , _, _)
234234 }
235235
236236 override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
@@ -242,34 +242,115 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
242242 * A node that represents the value of an expression _after_ implicit dereferencing
243243 * or borrowing.
244244 */
245- class DerefBorrowNode extends Node , TDerefBorrowNode {
245+ class ImplicitDerefNode extends Node , TImplicitDerefNode {
246246 AstNode n ;
247- boolean isBorrow ;
247+ DerefChain derefChain ;
248+ ImplicitDerefNodeState state ;
249+ int i ;
248250
249- DerefBorrowNode ( ) { this = TDerefBorrowNode ( n , isBorrow , false ) }
251+ ImplicitDerefNode ( ) { this = TImplicitDerefNode ( n , derefChain , state , i , false ) }
250252
251- AstNode getNode ( ) { result = n }
253+ Node getBorrowInputNode ( ) {
254+ state = TImplicitDerefNodeBorrowState ( ) and
255+ (
256+ i = 0 and
257+ result .( AstNodeNode ) .getAstNode ( ) = n
258+ or
259+ result = TImplicitDerefNode ( n , derefChain , TImplicitDerefNodeAfterDerefState ( ) , i - 1 , false )
260+ )
261+ }
252262
253- predicate isBorrow ( ) { isBorrow = true }
263+ Node getDerefOutputNode ( ) {
264+ state = TImplicitDerefNodeBeforeDerefState ( ) and
265+ result = TImplicitDerefNode ( n , derefChain , TImplicitDerefNodeAfterDerefState ( ) , i , false )
266+ }
267+
268+ predicate isLast ( AstNode node ) {
269+ this =
270+ TImplicitDerefNode ( node , derefChain , TImplicitDerefNodeAfterDerefState ( ) ,
271+ derefChain .length ( ) - 1 , false )
272+ }
254273
255274 override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
256275
257276 override Location getLocation ( ) { result = n .getLocation ( ) }
258277
259- override string toString ( ) {
260- if isBorrow = true then result = n + " [borrowed]" else result = n + " [dereferenced]"
278+ override string toString ( ) { result = n + " [implicit deref " + i + " in state " + state + "]" }
279+ }
280+
281+ /**
282+ * A node that represents the value of an argument of a call _after_ implicit
283+ * dereferencing or borrowing.
284+ */
285+ final class ImplicitDerefArgNode extends ImplicitDerefNode , ArgumentNode {
286+ private DataFlowCall call_ ;
287+ private RustDataFlow:: ArgumentPosition pos_ ;
288+
289+ ImplicitDerefArgNode ( ) {
290+ state = TImplicitDerefNodeBorrowState ( ) and
291+ call_ = TImplicitDerefCall ( n , derefChain , i , _) and
292+ pos_ .isSelf ( )
293+ or
294+ state = TImplicitDerefNodeAfterDerefState ( ) and
295+ i = derefChain .length ( ) - 1 and
296+ TypeInference:: implicitDerefChainBorrow ( n , derefChain , false ) and
297+ isArgumentForCall ( n , call_ .asCall ( ) , pos_ )
298+ }
299+
300+ override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
301+ call = call_ and pos = pos_
302+ }
303+ }
304+
305+ private class ImplicitDerefOutNode extends ImplicitDerefNode , OutNode {
306+ private DataFlowCall call ;
307+
308+ ImplicitDerefOutNode ( ) { state = TImplicitDerefNodeBeforeDerefState ( ) }
309+
310+ override DataFlowCall getCall ( ReturnKind kind ) {
311+ result = TImplicitDerefCall ( n , derefChain , i , _) and
312+ kind = TNormalReturnKind ( )
261313 }
262314}
263315
316+ /**
317+ * A node that represents the value of an expression _after_ implicit dereferencing
318+ * or borrowing.
319+ */
320+ class ImplicitBorrowNode extends Node , TImplicitBorrowNode {
321+ AstNode n ;
322+ DerefChain derefChain ;
323+
324+ ImplicitBorrowNode ( ) { this = TImplicitBorrowNode ( n , derefChain , false ) }
325+
326+ AstNode getNode ( ) { result = n }
327+
328+ Node getBorrowInputNode ( ) {
329+ result =
330+ TImplicitDerefNode ( n , derefChain , TImplicitDerefNodeAfterDerefState ( ) ,
331+ derefChain .length ( ) - 1 , false )
332+ or
333+ derefChain .isEmpty ( ) and
334+ result .( AstNodeNode ) .getAstNode ( ) = n
335+ }
336+
337+ // AstNode getNode() { result = n }
338+ override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
339+
340+ override Location getLocation ( ) { result = n .getLocation ( ) }
341+
342+ override string toString ( ) { result = n + " [implicit borrow]" }
343+ }
344+
264345/**
265346 * A node that represents the value of an argument of a call _after_ implicit
266347 * dereferencing or borrowing.
267348 */
268- final class DerefBorrowArgNode extends DerefBorrowNode , ArgumentNode {
349+ final class ImplicitBorrowArgNode extends ImplicitBorrowNode , ArgumentNode {
269350 private DataFlowCall call_ ;
270351 private RustDataFlow:: ArgumentPosition pos_ ;
271352
272- DerefBorrowArgNode ( ) { isArgumentForCall ( n , call_ .asCall ( ) , pos_ ) }
353+ ImplicitBorrowArgNode ( ) { isArgumentForCall ( n , call_ .asCall ( ) , pos_ ) }
273354
274355 override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
275356 call = call_ and pos = pos_
@@ -478,17 +559,36 @@ final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
478559 override Location getLocation ( ) { result = e .getLocation ( ) }
479560}
480561
481- final class DerefBorrowPostUpdateNode extends PostUpdateNode , TDerefBorrowNode {
482- private Expr arg ;
483- private boolean isBorrow ;
562+ final class ImplicitDerefPostUpdateNode extends PostUpdateNode , TImplicitDerefNode {
563+ AstNode n ;
564+ DerefChain derefChain ;
565+ ImplicitDerefNodeState state ;
566+ int i ;
484567
485- DerefBorrowPostUpdateNode ( ) { this = TDerefBorrowNode ( arg , isBorrow , true ) }
568+ ImplicitDerefPostUpdateNode ( ) { this = TImplicitDerefNode ( n , derefChain , state , i , true ) }
486569
487- override DerefBorrowNode getPreUpdateNode ( ) { result = TDerefBorrowNode ( arg , isBorrow , false ) }
570+ override ImplicitDerefNode getPreUpdateNode ( ) {
571+ result = TImplicitDerefNode ( n , derefChain , state , i , false )
572+ }
488573
489- override CfgScope getCfgScope ( ) { result = arg .getEnclosingCfgScope ( ) }
574+ override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
490575
491- override Location getLocation ( ) { result = arg .getLocation ( ) }
576+ override Location getLocation ( ) { result = n .getLocation ( ) }
577+ }
578+
579+ final class ImplicitBorrowPostUpdateNode extends PostUpdateNode , TImplicitBorrowNode {
580+ AstNode n ;
581+ DerefChain derefChain ;
582+
583+ ImplicitBorrowPostUpdateNode ( ) { this = TImplicitBorrowNode ( n , derefChain , true ) }
584+
585+ override ImplicitBorrowNode getPreUpdateNode ( ) {
586+ result = TImplicitBorrowNode ( n , derefChain , false )
587+ }
588+
589+ override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
590+
591+ override Location getLocation ( ) { result = n .getLocation ( ) }
492592}
493593
494594class DerefOutPostUpdateNode extends PostUpdateNode , TDerefOutNode {
@@ -544,6 +644,21 @@ final class CastNode extends ExprNode {
544644 CastNode ( ) { none ( ) }
545645}
546646
647+ newtype TImplicitDerefNodeState =
648+ TImplicitDerefNodeBorrowState ( ) or
649+ TImplicitDerefNodeBeforeDerefState ( ) or
650+ TImplicitDerefNodeAfterDerefState ( )
651+
652+ class ImplicitDerefNodeState extends TImplicitDerefNodeState {
653+ string toString ( ) {
654+ this = TImplicitDerefNodeBorrowState ( ) and result = "borrow"
655+ or
656+ this = TImplicitDerefNodeBeforeDerefState ( ) and result = "before deref"
657+ or
658+ this = TImplicitDerefNodeAfterDerefState ( ) and result = "after deref"
659+ }
660+ }
661+
547662cached
548663newtype TNode =
549664 TExprNode ( Expr e ) { e .hasEnclosingCfgScope ( ) and Stages:: DataFlowStage:: ref ( ) } or
@@ -575,12 +690,14 @@ newtype TNode =
575690 ]
576691 )
577692 } or
578- TDerefBorrowNode ( AstNode n , boolean borrow , Boolean isPost ) {
579- TypeInference:: implicitDeref ( n ) and
580- borrow = false
581- or
582- TypeInference:: implicitBorrow ( n , _) and
583- borrow = true
693+ TImplicitDerefNode (
694+ AstNode n , DerefChain derefChain , ImplicitDerefNodeState state , int i , Boolean isPost
695+ ) {
696+ TypeInference:: implicitDerefChainBorrow ( n , derefChain , _) and
697+ i in [ 0 .. derefChain .length ( ) - 1 ]
698+ } or
699+ TImplicitBorrowNode ( AstNode n , DerefChain derefChain , Boolean isPost ) {
700+ TypeInference:: implicitDerefChainBorrow ( n , derefChain , true )
584701 } or
585702 TDerefOutNode ( DerefExpr de , Boolean isPost ) or
586703 TIndexOutNode ( IndexExpr ie , Boolean isPost ) or
0 commit comments