@@ -141,8 +141,6 @@ final class ArgumentPosition extends ParameterPosition {
141141 * Holds if `arg` is an argument of `call` at the position `pos`.
142142 */
143143predicate isArgumentForCall ( Expr arg , Call call , ArgumentPosition pos ) {
144- // TODO: Handle index expressions as calls in data flow.
145- not call instanceof IndexExpr and
146144 arg = pos .getArgument ( call )
147145}
148146
@@ -316,6 +314,20 @@ private module Aliases {
316314 class LambdaCallKindAlias = LambdaCallKind ;
317315}
318316
317+ /**
318+ * Holds if `n` is the post-update node for the left-hand side of `assignment`.
319+ *
320+ * For such assignments, we add a local flow step from the right-hand side to
321+ * `n`, which means that for assignments like `*x = y`, we get an induced
322+ * reverse `*`-store step into `[post] x`.
323+ *
324+ * This also applies to field assignments, `x.field = y`, and index assignments,
325+ * `x[index] = y`.
326+ */
327+ predicate assignmentPostUpdateNode ( AssignmentExpr assignment , PostUpdateNode n ) {
328+ n .getPreUpdateNode ( ) .asExpr ( ) = assignment .getLhs ( )
329+ }
330+
319331module RustDataFlow implements InputSig< Location > {
320332 private import Aliases
321333 private import codeql.rust.dataflow.DataFlow
@@ -363,7 +375,9 @@ module RustDataFlow implements InputSig<Location> {
363375 node instanceof ClosureParameterNode or
364376 node instanceof DerefBorrowNode or
365377 node instanceof DerefOutNode or
378+ node instanceof IndexOutNode or
366379 node .asExpr ( ) instanceof ParenExpr or
380+ assignmentPostUpdateNode ( _, node ) or
367381 nodeIsHidden ( node .( PostUpdateNode ) .getPreUpdateNode ( ) )
368382 }
369383
@@ -386,6 +400,8 @@ module RustDataFlow implements InputSig<Location> {
386400 node .asPat ( ) = match .getAnArm ( ) .getPat ( )
387401 )
388402 or
403+ node .asExpr ( ) = any ( AssignmentExpr ae ) .getRhs ( )
404+ or
389405 FlowSummaryImpl:: Private:: Steps:: sourceLocalStep ( _, node , _)
390406 or
391407 FlowSummaryImpl:: Private:: Steps:: sinkLocalStep ( node , _, _)
@@ -488,6 +504,12 @@ module RustDataFlow implements InputSig<Location> {
488504 .( Node:: FlowSummaryNode )
489505 .getSummaryNode ( ) , TOptionalBarrier ( _) , nodeTo .( Node:: FlowSummaryNode ) .getSummaryNode ( ) ) and
490506 model = ""
507+ or
508+ exists ( AssignmentExpr assignment |
509+ nodeFrom .asExpr ( ) = assignment .getRhs ( ) and
510+ assignmentPostUpdateNode ( assignment , nodeTo ) and
511+ model = ""
512+ )
491513 }
492514
493515 /**
@@ -559,12 +581,6 @@ module RustDataFlow implements InputSig<Location> {
559581 access = c .( FieldContent ) .getAnAccess ( )
560582 )
561583 or
562- exists ( IndexExpr arr |
563- c instanceof ElementContent and
564- node1 .asExpr ( ) = arr .getBase ( ) and
565- node2 .asExpr ( ) = arr
566- )
567- or
568584 exists ( ForExpr for |
569585 c instanceof ElementContent and
570586 node1 .asExpr ( ) = for .getIterable ( ) and
@@ -590,6 +606,12 @@ module RustDataFlow implements InputSig<Location> {
590606 node2 .asExpr ( ) = deref
591607 )
592608 or
609+ exists ( IndexExpr index |
610+ c instanceof ReferenceContent and
611+ node1 .( IndexOutNode ) .getIndexExpr ( ) = index and
612+ node2 .asExpr ( ) = index
613+ )
614+ or
593615 // Read from function return
594616 exists ( DataFlowCall call |
595617 lambdaCall ( call , _, node1 ) and
@@ -652,9 +674,8 @@ module RustDataFlow implements InputSig<Location> {
652674
653675 pragma [ nomagic]
654676 private predicate referenceAssignment ( Node node1 , Node node2 , ReferenceContent c ) {
655- exists ( AssignmentExpr assignment , PrefixExpr deref |
677+ exists ( AssignmentExpr assignment , DerefExpr deref |
656678 assignment .getLhs ( ) = deref and
657- deref .getOperatorName ( ) = "*" and
658679 node1 .asExpr ( ) = assignment .getRhs ( ) and
659680 node2 .asExpr ( ) = deref .getExpr ( ) and
660681 exists ( c )
@@ -699,15 +720,17 @@ module RustDataFlow implements InputSig<Location> {
699720 node2 .( NameNode ) .getName ( ) = p .getName ( )
700721 )
701722 or
702- fieldAssignment ( node1 , node2 . ( PostUpdateNode ) . getPreUpdateNode ( ) , c )
703- or
704- referenceAssignment ( node1 , node2 . ( PostUpdateNode ) . getPreUpdateNode ( ) , c )
705- or
706- exists ( AssignmentExpr assignment , IndexExpr index |
723+ // Since generalized reverse flow is not yet supported, we add a special case
724+ // for assignments into arrays and slices
725+ exists ( IndexExpr index |
726+ node1 . ( PostUpdateNode ) . getPreUpdateNode ( ) . asExpr ( ) = index and
727+ node2 . ( PostUpdateNode ) . getPreUpdateNode ( ) . asExpr ( ) = index . getBase ( ) and
707728 c instanceof ElementContent and
708- assignment .getLhs ( ) = index and
709- node1 .asExpr ( ) = assignment .getRhs ( ) and
710- node2 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = index .getBase ( )
729+ index .getResolvedTarget ( ) .getCanonicalPath ( ) =
730+ [
731+ "<[;] as core::ops::index::IndexMut>::index_mut" ,
732+ "<[] as core::ops::index::IndexMut>::index_mut"
733+ ]
711734 )
712735 or
713736 referenceExprToExpr ( node1 , node2 , c )
@@ -989,9 +1012,7 @@ private module Cached {
9891012 newtype TDataFlowCall =
9901013 TCall ( Call call ) {
9911014 Stages:: DataFlowStage:: ref ( ) and
992- call .hasEnclosingCfgScope ( ) and
993- // TODO: Handle index expressions as calls in data flow.
994- not call instanceof IndexExpr
1015+ call .hasEnclosingCfgScope ( )
9951016 } or
9961017 TSummaryCall (
9971018 FlowSummaryImpl:: Public:: SummarizedCallable c , FlowSummaryImpl:: Private:: SummaryNode receiver
0 commit comments