Skip to content

Commit 09cfe5d

Browse files
committed
unified: Add flow through string interpolation
1 parent 098e7e0 commit 09cfe5d

3 files changed

Lines changed: 25 additions & 0 deletions

File tree

unified/ql/lib/codeql/unified/internal/FacadeAst.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,8 @@ module Unified {
197197
result = arg.getValue()
198198
)
199199
}
200+
201+
/** Gets the number of arguments passed to this call, not counting implicit arguments like receiver. */
202+
int getNumberOfArguments() { result = count(this.getAnArgument()) }
200203
}
201204
}

unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,23 @@ predicate step(Node node1, Step step, Node node2) {
4545
node2.isResultValue(expr)
4646
)
4747
or
48+
exists(StringInterpolationExpr expr |
49+
node1.isResultValue(expr.getAnElement()) and
50+
step.taint() and
51+
node2.isResultValue(expr)
52+
)
53+
or
54+
exists(CallExpr call |
55+
// String interpolations in Swift currently insert a call to a built-in called "interpolation".
56+
// Add taint through plain 1-argument calls to this built-in.
57+
call.getCallee().(BuiltinExpr).getValue() = "interpolation" and
58+
call.getNumberOfArguments() = 1 and
59+
not exists(call.getArgument(0).getName()) and
60+
node1.isResultValue(call.getArgument(0).getValue()) and
61+
step.value() and
62+
node2.isResultValue(call)
63+
)
64+
or
4865
exists(TupleExpr expr, int i |
4966
node1.isResultValue(expr.getElement(i).getValue()) and
5067
step.storeName(i.toString()) and

unified/ql/test/library-tests/dataflow/test.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ func t1() {
55
func t2() {
66
sink(source("t2.1") + "blah"); // $ hasTaintFlow=t2.1
77
sink("blah" + source("t2.2")); // $ hasTaintFlow=t2.2
8+
9+
sink("\(source("t2.3")) blah"); // $ hasTaintFlow=t2.3
10+
sink("blah \(source("t2.4"))"); // $ hasTaintFlow=t2.4
11+
sink("blah \(source("t2.5")) blah"); // $ hasTaintFlow=t2.5
12+
sink("blah \(escape: source("t2.6")) blah"); // no flow
813
}
914

1015
func t3() {

0 commit comments

Comments
 (0)