Swift: Flow (1) through the internal function calls generated by the compiler during string interpolation, and (2) out of the internal 'TapExpr' and into the interpolated string result.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-08-04 20:06:10 +01:00
parent 52b78b6e68
commit 9c48ce1bf2
2 changed files with 32 additions and 1 deletions

View File

@@ -39,6 +39,13 @@ predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain)
v instanceof ParamDecl and
bb.getNode(i).getNode().asAstNode() = v and
certain = true
or
// Mark the subexpression as a write of the local variable declared in the `TapExpr`.
exists(TapExpr tap |
v = tap.getVar() and
bb.getNode(i).getNode().asAstNode() = tap.getSubExpr() and
certain = true
)
}
private predicate isLValue(DeclRefExpr ref) { any(AssignExpr assign).getDest() = ref }
@@ -58,4 +65,11 @@ predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain)
bb.getScope() = func and
certain = true
)
or
// Mark the `TapExpr` as a read of the of the local variable.
exists(TapExpr tap |
v = tap.getVar() and
bb.getNode(i).getNode().asAstNode() = tap and
certain = true
)
}

View File

@@ -2,6 +2,8 @@ private import swift
private import DataFlowPrivate
private import TaintTrackingPublic
private import codeql.swift.dataflow.DataFlow
private import codeql.swift.dataflow.Ssa
private import codeql.swift.controlflow.CfgNodes
/**
* Holds if `node` should be a sanitizer in all global taint flow configurations
@@ -16,7 +18,22 @@ private module Cached {
* in all global taint flow configurations.
*/
cached
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { none() }
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// Flow through one argument of `appendLiteral` and `appendInterpolation` and to the second argument.
exists(ApplyExpr apply1, ApplyExpr apply2, ExprCfgNode e |
nodeFrom.asExpr() = [apply1, apply2].getAnArgument().getExpr() and
apply1.getFunction() = apply2 and
apply2.getStaticTarget().getName() = ["appendLiteral(_:)", "appendInterpolation(_:)"] and
e.getExpr() = apply2.getAnArgument().getExpr() and
nodeTo.asDefinition().(Ssa::WriteDefinition).isInoutDef(e)
)
or
// Flow from the computation of the interpolated string literal to the result of the interpolation.
exists(InterpolatedStringLiteralExpr interpolated |
nodeTo.asExpr() = interpolated and
nodeFrom.asExpr() = interpolated.getAppendingExpr()
)
}
/**
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local