@@ -12,7 +12,6 @@ private import codeql.rust.elements.Call
1212private import SsaImpl as SsaImpl
1313private import codeql.rust.controlflow.internal.Scope as Scope
1414private import codeql.rust.internal.PathResolution
15- private import codeql.rust.internal.TypeInference as TypeInference
1615private import codeql.rust.controlflow.ControlFlowGraph
1716private import codeql.rust.dataflow.Ssa
1817private import codeql.rust.dataflow.FlowSummary
@@ -58,8 +57,8 @@ final class DataFlowCallable extends TDataFlowCallable {
5857}
5958
6059final class DataFlowCall extends TDataFlowCall {
61- /** Gets the underlying call in the CFG , if any. */
62- Call asCall ( ) { this = TCall ( result ) }
60+ /** Gets the underlying function call , if any. */
61+ FunctionCall asFunctionCall ( ) { this = TFunctionCall ( result ) }
6362
6463 predicate isSummaryCall (
6564 FlowSummaryImpl:: Public:: SummarizedCallable c , FlowSummaryImpl:: Private:: SummaryNode receiver
@@ -68,13 +67,13 @@ final class DataFlowCall extends TDataFlowCall {
6867 }
6968
7069 DataFlowCallable getEnclosingCallable ( ) {
71- result .asCfgScope ( ) = this .asCall ( ) .getEnclosingCfgScope ( )
70+ result .asCfgScope ( ) = this .asFunctionCall ( ) .getEnclosingCfgScope ( )
7271 or
7372 this .isSummaryCall ( result .asSummarizedCallable ( ) , _)
7473 }
7574
7675 string toString ( ) {
77- result = this .asCall ( ) .toString ( )
76+ result = this .asFunctionCall ( ) .toString ( )
7877 or
7978 exists (
8079 FlowSummaryImpl:: Public:: SummarizedCallable c , FlowSummaryImpl:: Private:: SummaryNode receiver
@@ -84,13 +83,13 @@ final class DataFlowCall extends TDataFlowCall {
8483 )
8584 }
8685
87- Location getLocation ( ) { result = this .asCall ( ) .getLocation ( ) }
86+ Location getLocation ( ) { result = this .asFunctionCall ( ) .getLocation ( ) }
8887}
8988
9089/**
9190 * The position of a parameter in a function.
9291 *
93- * In Rust there is a 1-to-1 correspondence between parameter positions and
92+ * In Rust there is a 1-to-1 correspondence between parameter positions and
9493 * arguments positions, so we use the same underlying type for both.
9594 */
9695final class ParameterPosition extends TParameterPosition {
@@ -133,26 +132,18 @@ final class ParameterPosition extends TParameterPosition {
133132final class ArgumentPosition extends ParameterPosition {
134133 /** Gets the argument of `call` at this position, if any. */
135134 Expr getArgument ( Call call ) {
136- result = call .getPositionalArgument ( this .getPosition ( ) )
135+ result = call .getArgument ( this .getPosition ( ) )
137136 or
138- result = call .getReceiver ( ) and this .isSelf ( )
137+ this .isSelf ( ) and
138+ result = call .getReceiver ( )
139139 }
140140}
141141
142142/**
143143 * Holds if `arg` is an argument of `call` at the position `pos`.
144- *
145- * Note that this does not hold for the receiever expression of a method call
146- * as the synthetic `ReceiverNode` is the argument for the `self` parameter.
147144 */
148- predicate isArgumentForCall ( Expr arg , Call call , ParameterPosition pos ) {
149- // TODO: Handle index expressions as calls in data flow.
150- not call instanceof IndexExpr and
151- (
152- call .getPositionalArgument ( pos .getPosition ( ) ) = arg
153- or
154- call .getReceiver ( ) = arg and pos .isSelf ( ) and not call .receiverImplicitlyBorrowed ( )
155- )
145+ predicate isArgumentForCall ( Expr arg , FunctionCall call , ArgumentPosition pos ) {
146+ arg = pos .getArgument ( call )
156147}
157148
158149/** Provides logic related to SSA. */
@@ -283,14 +274,6 @@ module LocalFlow {
283274 or
284275 nodeFrom .asPat ( ) .( OrPat ) .getAPat ( ) = nodeTo .asPat ( )
285276 or
286- // Simple value step from receiver expression to receiver node, in case
287- // there is no implicit deref or borrow operation.
288- nodeFrom .asExpr ( ) = nodeTo .( ReceiverNode ) .getReceiver ( )
289- or
290- // The dual step of the above, for the post-update nodes.
291- nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .( ReceiverNode ) .getReceiver ( ) =
292- nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( )
293- or
294277 nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) =
295278 getPostUpdateReverseStep ( nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) , true )
296279 }
@@ -309,10 +292,8 @@ predicate lambdaCreationExpr(Expr creation) {
309292 * Holds if `call` is a lambda call of kind `kind` where `receiver` is the
310293 * invoked expression.
311294 */
312- predicate lambdaCallExpr ( CallExpr call , LambdaCallKind kind , Expr receiver ) {
295+ predicate lambdaCallExpr ( ClosureCall call , LambdaCallKind kind , Expr receiver ) {
313296 receiver = call .getFunction ( ) and
314- // All calls to complex expressions and local variable accesses are lambda call.
315- ( receiver instanceof PathExpr implies receiver = any ( Variable v ) .getAnAccess ( ) ) and
316297 exists ( kind )
317298}
318299
@@ -380,7 +361,7 @@ module RustDataFlow implements InputSig<Location> {
380361 node .( FlowSummaryNode ) .getSummaryNode ( ) .isHidden ( ) or
381362 node instanceof CaptureNode or
382363 node instanceof ClosureParameterNode or
383- node instanceof ReceiverNode or
364+ node instanceof DerefBorrowNode or
384365 node .asExpr ( ) instanceof ParenExpr or
385366 nodeIsHidden ( node .( PostUpdateNode ) .getPreUpdateNode ( ) )
386367 }
@@ -422,7 +403,7 @@ module RustDataFlow implements InputSig<Location> {
422403
423404 /** Gets a viable implementation of the target of the given `Call`. */
424405 DataFlowCallable viableCallable ( DataFlowCall call ) {
425- exists ( Call c | c = call .asCall ( ) |
406+ exists ( FunctionCall c | c = call .asFunctionCall ( ) |
426407 result .asCfgScope ( ) = c .getARuntimeTarget ( )
427408 or
428409 exists ( SummarizedCallable sc , Function staticTarget |
@@ -520,16 +501,16 @@ module RustDataFlow implements InputSig<Location> {
520501 }
521502
522503 pragma [ nomagic]
523- private predicate implicitDerefToReceiver ( Node node1 , ReceiverNode node2 , ReferenceContent c ) {
524- TypeInference :: receiverHasImplicitDeref ( node1 . asExpr ( ) ) and
525- node1 .asExpr ( ) = node2 .getReceiver ( ) and
504+ private predicate implicitDeref ( Node node1 , DerefBorrowNode node2 , ReferenceContent c ) {
505+ not node2 . isBorrow ( ) and
506+ node1 .asExpr ( ) = node2 .getNode ( ) and
526507 exists ( c )
527508 }
528509
529510 pragma [ nomagic]
530- private predicate implicitBorrowToReceiver ( Node node1 , ReceiverNode node2 , ReferenceContent c ) {
531- TypeInference :: receiverHasImplicitBorrow ( node1 . asExpr ( ) ) and
532- node1 .asExpr ( ) = node2 .getReceiver ( ) and
511+ private predicate implicitBorrow ( Node node1 , DerefBorrowNode node2 , ReferenceContent c ) {
512+ node2 . isBorrow ( ) and
513+ node1 .asExpr ( ) = node2 .getNode ( ) and
533514 exists ( c )
534515 }
535516
@@ -539,6 +520,15 @@ module RustDataFlow implements InputSig<Location> {
539520 exists ( c )
540521 }
541522
523+ private Node getFieldExprContainerNode ( FieldExpr fe ) {
524+ exists ( Expr container | container = fe .getContainer ( ) |
525+ not any ( DerefBorrowNode n ) .getNode ( ) = container and
526+ result .asExpr ( ) = container
527+ or
528+ result .( DerefBorrowNode ) .getNode ( ) = container
529+ )
530+ }
531+
542532 pragma [ nomagic]
543533 additional predicate readContentStep ( Node node1 , Content c , Node node2 ) {
544534 exists ( TupleStructPat pat , int pos |
@@ -563,9 +553,9 @@ module RustDataFlow implements InputSig<Location> {
563553 node1 .asPat ( ) .( RefPat ) .getPat ( ) = node2 .asPat ( )
564554 or
565555 exists ( FieldExpr access |
566- node1 .asExpr ( ) = access .getContainer ( ) and
567556 node2 .asExpr ( ) = access and
568- access = c .( FieldContent ) .getAnAccess ( )
557+ access = c .( FieldContent ) .getAnAccess ( ) and
558+ node1 = getFieldExprContainerNode ( access )
569559 )
570560 or
571561 exists ( IndexExpr arr |
@@ -616,12 +606,10 @@ module RustDataFlow implements InputSig<Location> {
616606 referenceExprToExpr ( node2 .( PostUpdateNode ) .getPreUpdateNode ( ) ,
617607 node1 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
618608 or
619- // Step from receiver expression to receiver node, in case of an implicit
620- // dereference.
621- implicitDerefToReceiver ( node1 , node2 , c )
609+ implicitDeref ( node1 , node2 , c )
622610 or
623611 // A read step dual to the store step for implicit borrows.
624- implicitBorrowToReceiver ( node2 .( PostUpdateNode ) .getPreUpdateNode ( ) ,
612+ implicitBorrow ( node2 .( PostUpdateNode ) .getPreUpdateNode ( ) ,
625613 node1 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
626614 or
627615 VariableCapture:: readStep ( node1 , c , node2 )
@@ -657,7 +645,7 @@ module RustDataFlow implements InputSig<Location> {
657645 exists ( AssignmentExpr assignment , FieldExpr access |
658646 assignment .getLhs ( ) = access and
659647 node1 .asExpr ( ) = assignment .getRhs ( ) and
660- node2 . asExpr ( ) = access . getContainer ( ) and
648+ node2 = getFieldExprContainerNode ( access ) and
661649 access = c .getAnAccess ( )
662650 )
663651 }
@@ -676,7 +664,7 @@ module RustDataFlow implements InputSig<Location> {
676664 pragma [ nomagic]
677665 additional predicate storeContentStep ( Node node1 , Content c , Node node2 ) {
678666 exists ( CallExpr call , int pos |
679- node1 .asExpr ( ) = call .getArg ( pragma [ only_bind_into ] ( pos ) ) and
667+ node1 .asExpr ( ) = call .getArgument ( pragma [ only_bind_into ] ( pos ) ) and
680668 node2 .asExpr ( ) = call and
681669 c = TTupleFieldContent ( call .getTupleField ( pragma [ only_bind_into ] ( pos ) ) )
682670 )
@@ -729,9 +717,11 @@ module RustDataFlow implements InputSig<Location> {
729717 or
730718 VariableCapture:: storeStep ( node1 , c , node2 )
731719 or
732- // Step from receiver expression to receiver node, in case of an implicit
733- // borrow.
734- implicitBorrowToReceiver ( node1 , node2 , c )
720+ implicitBorrow ( node1 , node2 , c )
721+ or
722+ // A store step dual to the read step for implicit dereferences.
723+ implicitDeref ( node2 .( PostUpdateNode ) .getPreUpdateNode ( ) ,
724+ node1 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
735725 }
736726
737727 /**
@@ -835,11 +825,7 @@ module RustDataFlow implements InputSig<Location> {
835825 */
836826 predicate lambdaCall ( DataFlowCall call , LambdaCallKind kind , Node receiver ) {
837827 (
838- receiver .asExpr ( ) = call .asCall ( ) .( CallExpr ) .getFunction ( ) and
839- // All calls to complex expressions and local variable accesses are lambda call.
840- exists ( Expr f | f = receiver .asExpr ( ) |
841- f instanceof PathExpr implies f = any ( Variable v ) .getAnAccess ( )
842- )
828+ receiver .asExpr ( ) = call .asFunctionCall ( ) .( ClosureCall ) .getFunction ( )
843829 or
844830 call .isSummaryCall ( _, receiver .( FlowSummaryNode ) .getSummaryNode ( ) )
845831 ) and
@@ -1001,11 +987,9 @@ private module Cached {
1001987
1002988 cached
1003989 newtype TDataFlowCall =
1004- TCall ( Call call ) {
990+ TFunctionCall ( FunctionCall call ) {
1005991 Stages:: DataFlowStage:: ref ( ) and
1006- call .hasEnclosingCfgScope ( ) and
1007- // TODO: Handle index expressions as calls in data flow.
1008- not call instanceof IndexExpr
992+ call .hasEnclosingCfgScope ( )
1009993 } or
1010994 TSummaryCall (
1011995 FlowSummaryImpl:: Public:: SummarizedCallable c , FlowSummaryImpl:: Private:: SummaryNode receiver
@@ -1033,10 +1017,8 @@ private module Cached {
10331017 cached
10341018 newtype TParameterPosition =
10351019 TPositionalParameterPosition ( int i ) {
1036- i in [ 0 .. max ( [ any ( ParamList l ) .getNumberOfParams ( ) , any ( ArgList l ) .getNumberOfArgs ( ) ] ) - 1 ]
1037- or
1038- FlowSummaryImpl:: ParsePositions:: isParsedArgumentPosition ( _, i )
1039- or
1020+ i in [ 0 .. max ( [ any ( ParamList l ) .getNumberOfParams ( ) , any ( ArgList l ) .getNumberOfArgs ( ) ] ) - 1 ] or
1021+ FlowSummaryImpl:: ParsePositions:: isParsedArgumentPosition ( _, i ) or
10401022 FlowSummaryImpl:: ParsePositions:: isParsedParameterPosition ( _, i )
10411023 } or
10421024 TClosureSelfParameterPosition ( ) or
0 commit comments