@@ -90,10 +90,10 @@ final class DataFlowCall extends TDataFlowCall {
9090}
9191
9292/**
93- * The position of a parameter or an argument in a function or call .
93+ * The position of a parameter in a function.
9494 *
95- * As there is a 1-to-1 correspondence between parameter positions and
96- * arguments positions in Rust we use the same type for both.
95+ * In Rust there is a 1-to-1 correspondence between parameter positions and
96+ * arguments positions, so we use the same underlying type for both.
9797 */
9898final class ParameterPosition extends TParameterPosition {
9999 /** Gets the underlying integer position, if any. */
@@ -126,6 +126,22 @@ final class ParameterPosition extends TParameterPosition {
126126 }
127127}
128128
129+ /**
130+ * The position of an argument in a call.
131+ *
132+ * In Rust there is a 1-to-1 correspondence between parameter positions and
133+ * arguments positions, so we use the same underlying type for both.
134+ */
135+ final class ArgumentPosition extends ParameterPosition {
136+ /** Gets the argument of `call` at this position, if any. */
137+ Expr getArgument ( CallExprBase call ) {
138+ result = call .getArgList ( ) .getArg ( this .getPosition ( ) )
139+ or
140+ this .isSelf ( ) and
141+ result = call .( MethodCallExpr ) .getReceiver ( )
142+ }
143+ }
144+
129145/** Holds if `call` invokes a qualified path that resolves to a method. */
130146private predicate callToMethod ( CallExpr call ) {
131147 exists ( Path path |
@@ -197,6 +213,28 @@ private ExprCfgNode getALastEvalNode(ExprCfgNode e) {
197213 result .( BreakExprCfgNode ) .getTarget ( ) = e
198214}
199215
216+ /**
217+ * Holds if a reverse local flow step should be added from the post-update node
218+ * for `e` to the post-update node for the result.
219+ *
220+ * This is needed to allow for side-effects on compound expressions to propagate
221+ * to sub components. For example, in
222+ *
223+ * ```rust
224+ * ({ foo(); &mut a}).set_data(taint);
225+ * ```
226+ *
227+ * we add a reverse flow step from `[post] { foo(); &mut a}` to `[post] &mut a`,
228+ * in order for the side-effect of `set_data` to reach `&mut a`.
229+ */
230+ ExprCfgNode getPostUpdateReverseStep ( ExprCfgNode e , boolean preservesValue ) {
231+ result = getALastEvalNode ( e ) and
232+ preservesValue = true
233+ or
234+ result = e .( CastExprCfgNode ) .getExpr ( ) and
235+ preservesValue = false
236+ }
237+
200238module LocalFlow {
201239 predicate flowSummaryLocalStep ( Node nodeFrom , Node nodeTo , string model ) {
202240 exists ( FlowSummaryImpl:: Public:: SummarizedCallable c |
@@ -258,6 +296,9 @@ module LocalFlow {
258296 // The dual step of the above, for the post-update nodes.
259297 nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .( ReceiverNode ) .getReceiver ( ) =
260298 nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( )
299+ or
300+ nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) =
301+ getPostUpdateReverseStep ( nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) , true )
261302 }
262303}
263304
@@ -432,6 +473,8 @@ private module Aliases {
432473
433474 class ParameterPositionAlias = ParameterPosition ;
434475
476+ class ArgumentPositionAlias = ArgumentPosition ;
477+
435478 class ContentAlias = Content ;
436479
437480 class ContentSetAlias = ContentSet ;
@@ -550,7 +593,7 @@ module RustDataFlow implements InputSig<Location> {
550593
551594 class ParameterPosition = ParameterPositionAlias ;
552595
553- class ArgumentPosition = ParameterPosition ;
596+ class ArgumentPosition = ArgumentPositionAlias ;
554597
555598 /**
556599 * Holds if the parameter position `ppos` matches the argument position
0 commit comments