@@ -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,103 @@ 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+ // i = derefChain.length() - 1 and
268+ // result.(AstNodeNode).getAstNode() = n
269+ // or
270+ // result = TImplicitDerefNode(n, derefChain, TImplicitDerefNodeAfterDerefState(), i - 1, false)
271+ // )
272+ }
254273
274+ // AstNode getNode() { result = n }
255275 override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
256276
257277 override Location getLocation ( ) { result = n .getLocation ( ) }
258278
259- override string toString ( ) {
260- if isBorrow = true then result = n + " [borrowed]" else result = n + " [dereferenced]"
279+ override string toString ( ) { result = n + " [implicit deref " + i + " in state " + state + "]" }
280+ }
281+
282+ /**
283+ * A node that represents the value of an argument of a call _after_ implicit
284+ * dereferencing or borrowing.
285+ */
286+ final class ImplicitDerefArgNode extends ImplicitDerefNode , ArgumentNode {
287+ private DataFlowCall call_ ;
288+ private RustDataFlow:: ArgumentPosition pos_ ;
289+
290+ ImplicitDerefArgNode ( ) {
291+ state = TImplicitDerefNodeBorrowState ( ) and
292+ call_ = TImplicitDerefCall ( n , derefChain , i , _) and
293+ pos_ .isSelf ( )
294+ or
295+ state = TImplicitDerefNodeAfterDerefState ( ) and
296+ i = derefChain .length ( ) - 1 and
297+ TypeInference:: implicitDerefChainBorrow ( n , derefChain , false ) and
298+ isArgumentForCall ( n , call_ .asCall ( ) , pos_ )
299+ }
300+
301+ override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
302+ call = call_ and pos = pos_
303+ }
304+ }
305+
306+ /**
307+ * A node that represents the value of an expression _after_ implicit dereferencing
308+ * or borrowing.
309+ */
310+ class ImplicitBorrowNode extends Node , TImplicitBorrowNode {
311+ AstNode n ;
312+ DerefChain derefChain ;
313+
314+ ImplicitBorrowNode ( ) { this = TImplicitBorrowNode ( n , derefChain , false ) }
315+
316+ Node getBorrowInputNode ( ) {
317+ result =
318+ TImplicitDerefNode ( n , derefChain , TImplicitDerefNodeAfterDerefState ( ) ,
319+ derefChain .length ( ) - 1 , false )
320+ or
321+ derefChain .isEmpty ( ) and
322+ result .( AstNodeNode ) .getAstNode ( ) = n
261323 }
324+
325+ // AstNode getNode() { result = n }
326+ override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
327+
328+ override Location getLocation ( ) { result = n .getLocation ( ) }
329+
330+ override string toString ( ) { result = n + " [implicit borrow]" }
262331}
263332
264333/**
265334 * A node that represents the value of an argument of a call _after_ implicit
266335 * dereferencing or borrowing.
267336 */
268- final class DerefBorrowArgNode extends DerefBorrowNode , ArgumentNode {
337+ final class ImplicitBorrowArgNode extends ImplicitBorrowNode , ArgumentNode {
269338 private DataFlowCall call_ ;
270339 private RustDataFlow:: ArgumentPosition pos_ ;
271340
272- DerefBorrowArgNode ( ) { isArgumentForCall ( n , call_ .asCall ( ) , pos_ ) }
341+ ImplicitBorrowArgNode ( ) { isArgumentForCall ( n , call_ .asCall ( ) , pos_ ) }
273342
274343 override predicate isArgumentOf ( DataFlowCall call , RustDataFlow:: ArgumentPosition pos ) {
275344 call = call_ and pos = pos_
@@ -478,17 +547,36 @@ final class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
478547 override Location getLocation ( ) { result = e .getLocation ( ) }
479548}
480549
481- final class DerefBorrowPostUpdateNode extends PostUpdateNode , TDerefBorrowNode {
482- private Expr arg ;
483- private boolean isBorrow ;
550+ final class ImplicitDerefPostUpdateNode extends PostUpdateNode , TImplicitDerefNode {
551+ AstNode n ;
552+ DerefChain derefChain ;
553+ ImplicitDerefNodeState state ;
554+ int i ;
484555
485- DerefBorrowPostUpdateNode ( ) { this = TDerefBorrowNode ( arg , isBorrow , true ) }
556+ ImplicitDerefPostUpdateNode ( ) { this = TImplicitDerefNode ( n , derefChain , state , i , true ) }
486557
487- override DerefBorrowNode getPreUpdateNode ( ) { result = TDerefBorrowNode ( arg , isBorrow , false ) }
558+ override ImplicitDerefNode getPreUpdateNode ( ) {
559+ result = TImplicitDerefNode ( n , derefChain , state , i , false )
560+ }
488561
489- override CfgScope getCfgScope ( ) { result = arg .getEnclosingCfgScope ( ) }
562+ override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
490563
491- override Location getLocation ( ) { result = arg .getLocation ( ) }
564+ override Location getLocation ( ) { result = n .getLocation ( ) }
565+ }
566+
567+ final class ImplicitBorrowPostUpdateNode extends PostUpdateNode , TImplicitBorrowNode {
568+ AstNode n ;
569+ DerefChain derefChain ;
570+
571+ ImplicitBorrowPostUpdateNode ( ) { this = TImplicitBorrowNode ( n , derefChain , true ) }
572+
573+ override ImplicitBorrowNode getPreUpdateNode ( ) {
574+ result = TImplicitBorrowNode ( n , derefChain , false )
575+ }
576+
577+ override CfgScope getCfgScope ( ) { result = n .getEnclosingCfgScope ( ) }
578+
579+ override Location getLocation ( ) { result = n .getLocation ( ) }
492580}
493581
494582class DerefOutPostUpdateNode extends PostUpdateNode , TDerefOutNode {
@@ -544,6 +632,21 @@ final class CastNode extends ExprNode {
544632 CastNode ( ) { none ( ) }
545633}
546634
635+ newtype TImplicitDerefNodeState =
636+ TImplicitDerefNodeBorrowState ( ) or
637+ TImplicitDerefNodeBeforeDerefState ( ) or
638+ TImplicitDerefNodeAfterDerefState ( )
639+
640+ class ImplicitDerefNodeState extends TImplicitDerefNodeState {
641+ string toString ( ) {
642+ this = TImplicitDerefNodeBorrowState ( ) and result = "borrow"
643+ or
644+ this = TImplicitDerefNodeBeforeDerefState ( ) and result = "before deref"
645+ or
646+ this = TImplicitDerefNodeAfterDerefState ( ) and result = "after deref"
647+ }
648+ }
649+
547650cached
548651newtype TNode =
549652 TExprNode ( Expr e ) { e .hasEnclosingCfgScope ( ) and Stages:: DataFlowStage:: ref ( ) } or
@@ -575,12 +678,14 @@ newtype TNode =
575678 ]
576679 )
577680 } 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
681+ TImplicitDerefNode (
682+ AstNode n , DerefChain derefChain , ImplicitDerefNodeState state , int i , Boolean isPost
683+ ) {
684+ TypeInference:: implicitDerefChainBorrow ( n , derefChain , _) and
685+ i in [ 0 .. derefChain .length ( ) - 1 ]
686+ } or
687+ TImplicitBorrowNode ( AstNode n , DerefChain derefChain , Boolean isPost ) {
688+ TypeInference:: implicitDerefChainBorrow ( n , derefChain , true )
584689 } or
585690 TDerefOutNode ( DerefExpr de , Boolean isPost ) or
586691 TIndexOutNode ( IndexExpr ie , Boolean isPost ) or
0 commit comments