44
55private import unified
66private import AllDataFlow
7+ private import codeql.unified.internal.ExprPositions
8+ private import codeql.unified.internal.typeinference.TypeInference as T
79
810private class SwiftDataFlowPlugin extends DataFlowPlugin {
911 // Note: For now we assume all code is Swift, but in the future we must restrict these rules to Swift-files
@@ -13,7 +15,10 @@ private class SwiftDataFlowPlugin extends DataFlowPlugin {
1315
1416 // Swift writes back mutated values of computed properties via their setter
1517 bindingset [ expr]
16- override predicate mayWriteBackViaSetterCall ( Expr expr ) { any ( ) }
18+ override predicate mayWriteBackViaSetterCall ( Expr expr ) {
19+ isInWriteBackPosition ( expr )
20+ // TODO: Check that 'expr' has a value type. Reference types don't cause writebacks.
21+ }
1722
1823 override predicate exprStep ( Expr expr1 , Expr expr2 , boolean mustFlow ) {
1924 mustFlow = true and
@@ -90,3 +95,30 @@ private class SwiftDataFlowPlugin extends DataFlowPlugin {
9095 )
9196 }
9297}
98+
99+ /**
100+ * Holds if `expr` is target of an assignment or 'inout' argument,
101+ * or the base of such an expression, e.g. `x` in `x.f1.f2 = foo()`
102+ */
103+ private predicate isInWriteBackPosition ( Expr expr ) {
104+ isInAssignmentContext ( expr , _)
105+ or
106+ // Arguments to an 'inout' parameter must be prefixed with '&'
107+ exists ( UnaryExpr unary |
108+ unary .getOperator ( ) .( PrefixOperator ) .getValue ( ) = "&" and
109+ unary .getOperand ( ) = expr
110+ // TODO: support custom operators with an 'inout' parameter, which lack the '&' indicator
111+ )
112+ or
113+ // The receiver of a call to a 'mutating' function counts as an 'inout' argument
114+ exists ( CallExpr call , Callable target |
115+ target = T:: resolveCallTarget ( call ) and
116+ target .hasModifier ( "mutating" ) and
117+ expr = call .getCallee ( ) .( MemberAccessExpr ) .getBase ( )
118+ )
119+ or
120+ exists ( MemberAccessExpr member |
121+ isInWriteBackPosition ( member ) and
122+ expr = member .getBase ( )
123+ )
124+ }
0 commit comments