Skip to content

Commit 8a1450c

Browse files
committed
unified: Add a hook for writebacks
Writebacks are a language-specific thing so let's add a hook for it
1 parent 0ce6d12 commit 8a1450c

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ private newtype TDataFlowCall =
2020
isInAssignmentContext(expr, _)
2121
or
2222
// Write back a value that was mutated in-place, such as `x.p` in `x.p.f = y`
23-
isMutatedByCallOrAssign(expr, _)
23+
isMutatedByCallOrAssign(expr, _) and
24+
mayWriteBackViaSetterCall(expr)
2425
) and
2526
(
2627
N::getStaticBindingTargetFromRef(expr) = any(SetterDeclaration g).getNameNode()

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPlugin.qll‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ class DataFlowPlugin extends Unit {
2626
* This affects the steps generated by the language-agnostic code as well as steps from the plugin itself.
2727
*/
2828
predicate bypassContentSet(ContentSet contents) { none() }
29+
30+
/**
31+
* Holds if mutating the value of `expr` in-place, such as `expr.f = y` or `expr.mutate()`,
32+
* may cause the mutated value to be written back via a setter call.
33+
*
34+
* `expr` is an expression in getter position, such as a member access.
35+
*/
36+
bindingset[expr]
37+
predicate mayWriteBackViaSetterCall(Expr expr) { none() }
2938
}
3039

3140
/**
@@ -40,3 +49,12 @@ predicate bypassContentSet(ContentSet contents) { any(DataFlowPlugin p).bypassCo
4049
predicate exprStep(Expr expr1, Expr expr2, boolean mustFlow) {
4150
any(DataFlowPlugin p).exprStep(expr1, expr2, mustFlow)
4251
}
52+
53+
/**
54+
* Holds if mutating the value of `expr` in-place, such as `expr.f = y` or `expr.mutate()`,
55+
* may cause the mutated value to be written back via a setter call.
56+
*/
57+
bindingset[expr]
58+
predicate mayWriteBackViaSetterCall(Expr expr) {
59+
any(DataFlowPlugin p).mayWriteBackViaSetterCall(expr)
60+
}

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ private class SwiftDataFlowPlugin extends DataFlowPlugin {
1111
contents.asSingleton().asNamedMember() = "some.0"
1212
}
1313

14+
// Swift writes back mutated values of computed properties via their setter
15+
bindingset[expr]
16+
override predicate mayWriteBackViaSetterCall(Expr expr) { any() }
17+
1418
override predicate exprStep(Expr expr1, Expr expr2, boolean mustFlow) {
1519
mustFlow = true and
1620
exists(UnaryExpr expr |

0 commit comments

Comments
 (0)