Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 40 additions & 18 deletions swift/ql/test/TestUtilities/InlineFlowTest.qll
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
* To declare expectations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files.
* Example of the corresponding test file, e.g. Test.java
* ```swift
* func source() -> Any { return nil }
* func taint() -> Any { return nil }
* func source(_ label: String) -> Any { return nil }
* func taint(_ label: String) -> Any { return nil }
* func sink(_ o: Any) { }
*
* func test() {
* let s = source()
* sink(s) // $ hasValueFlow
* let t = "foo" + taint()
* sink(t); // $ hasTaintFlow
* let s = source("mySource")
* sink(s) // $ hasValueFlow=mySource
* let t = "foo" + taint("myTaint")
* sink(t); // $ hasTaintFlow=myTaint
* }
* ```
*
Expand All @@ -42,11 +42,17 @@ import codeql.swift.dataflow.TaintTracking
import TestUtilities.InlineExpectationsTest

private predicate defaultSource(DataFlow::Node source) {
source.asExpr().(CallExpr).getStaticTarget().(Function).getShortName() = ["source", "taint"]
source
.asExpr()
.(CallExpr)
.getStaticTarget()
.(Function)
.getShortName()
.matches(["source%", "taint"])
}

private predicate defaultSink(DataFlow::Node sink) {
exists(CallExpr ca | ca.getStaticTarget().(Function).getShortName() = "sink" |
exists(CallExpr ca | ca.getStaticTarget().(Function).getShortName().matches("sink%") |
sink.asExpr() = ca.getAnArgument().getExpr()
)
}
Expand All @@ -59,40 +65,55 @@ module DefaultFlowConfig implements DataFlow::ConfigSig {
int fieldFlowBranchLimit() { result = 1000 }
}

private module NoFlowConfig implements DataFlow::ConfigSig {
module NoFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { none() }

predicate isSink(DataFlow::Node sink) { none() }
}

private signature string valueFlowTagSig();

private signature string taintFlowTagSig();

string defaultValueFlowTag() { result = "hasValueFlow" }

string defaultTaintFlowTag() { result = "hasTaintFlow" }

private string getSourceArgString(DataFlow::Node src) {
defaultSource(src) and
src.asExpr().(CallExpr).getAnArgument().getExpr().(StringLiteralExpr).getValue() = result
}

module FlowTest<DataFlow::ConfigSig ValueFlowConfig, DataFlow::ConfigSig TaintFlowConfig> {
module FlowTest<
DataFlow::ConfigSig ValueFlowConfig, DataFlow::ConfigSig TaintFlowConfig,
valueFlowTagSig/0 valueFlowTag, taintFlowTagSig/0 taintFlowTag>
{
module ValueFlow = DataFlow::Global<ValueFlowConfig>;

module TaintFlow = TaintTracking::Global<TaintFlowConfig>;

private module InlineTest implements TestSig {
string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
string getARelevantTag() { result = [valueFlowTag(), taintFlowTag()] }

predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasValueFlow" and
tag = valueFlowTag() and
exists(DataFlow::Node src, DataFlow::Node sink | ValueFlow::flow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
if exists(getSourceArgString(src))
then value = getSourceArgString(src)
else value = src.getLocation().getStartLine().toString()
)
or
tag = "hasTaintFlow" and
tag = taintFlowTag() and
exists(DataFlow::Node src, DataFlow::Node sink |
TaintFlow::flow(src, sink) and not ValueFlow::flow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
if exists(getSourceArgString(src))
then value = getSourceArgString(src)
else value = src.getLocation().getStartLine().toString()
)
}
}
Expand All @@ -106,12 +127,13 @@ module FlowTest<DataFlow::ConfigSig ValueFlowConfig, DataFlow::ConfigSig TaintFl
}
}

module DefaultFlowTest = FlowTest<DefaultFlowConfig, DefaultFlowConfig>;
module DefaultFlowTest =
FlowTest<DefaultFlowConfig, DefaultFlowConfig, defaultValueFlowTag/0, defaultTaintFlowTag/0>;

module ValueFlowTest<DataFlow::ConfigSig ValueFlowConfig> {
import FlowTest<ValueFlowConfig, NoFlowConfig>
import FlowTest<ValueFlowConfig, NoFlowConfig, defaultValueFlowTag/0, defaultTaintFlowTag/0>
}

module TaintFlowTest<DataFlow::ConfigSig TaintFlowConfig> {
import FlowTest<NoFlowConfig, TaintFlowConfig>
import FlowTest<NoFlowConfig, TaintFlowConfig, defaultValueFlowTag/0, defaultTaintFlowTag/0>
}
24 changes: 12 additions & 12 deletions swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,8 @@ edges
| test.swift:884:15:884:15 | generator [Collection element] | test.swift:884:15:884:30 | call to next() [some:0] |
| test.swift:884:15:884:30 | call to next() [some:0] | test.swift:884:15:884:31 | ...! |
| test.swift:908:19:908:26 | call to source() | test.swift:904:13:904:18 | call to ... |
| test.swift:927:12:927:21 | call to source() | test.swift:927:12:927:21 | OpenExistentialExpr |
| test.swift:929:12:929:35 | call to source() | test.swift:929:12:929:35 | OpenExistentialExpr |
| test.swift:927:12:927:31 | call to source(_:) | test.swift:927:12:927:31 | OpenExistentialExpr |
| test.swift:929:12:929:57 | call to source(_:) | test.swift:929:12:929:57 | OpenExistentialExpr |
nodes
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
| file://:0:0:0:0 | .s [x] | semmle.label | .s [x] |
Expand Down Expand Up @@ -1256,12 +1256,12 @@ nodes
| test.swift:884:15:884:31 | ...! | semmle.label | ...! |
| test.swift:904:13:904:18 | call to ... | semmle.label | call to ... |
| test.swift:908:19:908:26 | call to source() | semmle.label | call to source() |
| test.swift:927:12:927:21 | OpenExistentialExpr | semmle.label | OpenExistentialExpr |
| test.swift:927:12:927:21 | call to source() | semmle.label | call to source() |
| test.swift:928:12:928:21 | call to source() | semmle.label | call to source() |
| test.swift:929:12:929:35 | OpenExistentialExpr | semmle.label | OpenExistentialExpr |
| test.swift:929:12:929:35 | call to source() | semmle.label | call to source() |
| test.swift:930:12:930:39 | call to source() | semmle.label | call to source() |
| test.swift:927:12:927:31 | OpenExistentialExpr | semmle.label | OpenExistentialExpr |
| test.swift:927:12:927:31 | call to source(_:) | semmle.label | call to source(_:) |
| test.swift:928:12:928:31 | call to source(_:) | semmle.label | call to source(_:) |
| test.swift:929:12:929:57 | OpenExistentialExpr | semmle.label | OpenExistentialExpr |
| test.swift:929:12:929:57 | call to source(_:) | semmle.label | call to source(_:) |
| test.swift:930:12:930:65 | call to source(_:) | semmle.label | call to source(_:) |
subpaths
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
Expand Down Expand Up @@ -1460,7 +1460,7 @@ subpaths
| test.swift:880:19:880:19 | elem | test.swift:877:21:877:28 | call to source() | test.swift:880:19:880:19 | elem | result |
| test.swift:884:15:884:31 | ...! | test.swift:877:21:877:28 | call to source() | test.swift:884:15:884:31 | ...! | result |
| test.swift:904:13:904:18 | call to ... | test.swift:908:19:908:26 | call to source() | test.swift:904:13:904:18 | call to ... | result |
| test.swift:927:12:927:21 | OpenExistentialExpr | test.swift:927:12:927:21 | call to source() | test.swift:927:12:927:21 | OpenExistentialExpr | result |
| test.swift:928:12:928:21 | call to source() | test.swift:928:12:928:21 | call to source() | test.swift:928:12:928:21 | call to source() | result |
| test.swift:929:12:929:35 | OpenExistentialExpr | test.swift:929:12:929:35 | call to source() | test.swift:929:12:929:35 | OpenExistentialExpr | result |
| test.swift:930:12:930:39 | call to source() | test.swift:930:12:930:39 | call to source() | test.swift:930:12:930:39 | call to source() | result |
| test.swift:927:12:927:31 | OpenExistentialExpr | test.swift:927:12:927:31 | call to source(_:) | test.swift:927:12:927:31 | OpenExistentialExpr | result |
| test.swift:928:12:928:31 | call to source(_:) | test.swift:928:12:928:31 | call to source(_:) | test.swift:928:12:928:31 | call to source(_:) | result |
| test.swift:929:12:929:57 | OpenExistentialExpr | test.swift:929:12:929:57 | call to source(_:) | test.swift:929:12:929:57 | OpenExistentialExpr | result |
| test.swift:930:12:930:65 | call to source(_:) | test.swift:930:12:930:65 | call to source(_:) | test.swift:930:12:930:65 | call to source(_:) | result |
20 changes: 3 additions & 17 deletions swift/ql/test/library-tests/dataflow/dataflow/DataFlowInline.ql
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
import swift
import TestUtilities.InlineFlowTest
import FlowConfig
import TestUtilities.InlineExpectationsTest

module TaintTest implements TestSig {
string getARelevantTag() { result = "flow" }
string customTaintFlowTag() { result = "flow" }

predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node source, DataFlow::Node sink, Expr sinkExpr |
TestFlow::flow(source, sink) and
sinkExpr = sink.asExpr() and
location = sinkExpr.getLocation() and
element = sinkExpr.toString() and
tag = "flow" and
value = source.asExpr().getLocation().getStartLine().toString()
)
}
}

import MakeTest<TaintTest>
import FlowTest<DefaultFlowConfig, NoFlowConfig, customTaintFlowTag/0, defaultTaintFlowTag/0>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import codeql.swift.frameworks.Frameworks

module TestConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
src.asExpr().(CallExpr).getStaticTarget().getName().matches("source%()")
src.asExpr().(CallExpr).getStaticTarget().getName().matches("source%")
}

predicate isSink(DataFlow::Node sink) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1159,11 +1159,11 @@
| test.swift:917:7:917:7 | SSA def(self) | test.swift:917:7:917:7 | self[return] |
| test.swift:917:7:917:7 | self | test.swift:917:7:917:7 | SSA def(self) |
| test.swift:917:7:917:7 | self | test.swift:917:7:917:7 | SSA def(self) |
| test.swift:918:7:918:7 | SSA def(self) | test.swift:918:2:918:34 | self[return] |
| test.swift:918:7:918:7 | SSA def(self) | test.swift:918:2:918:49 | self[return] |
| test.swift:918:7:918:7 | self | test.swift:918:7:918:7 | SSA def(self) |
| test.swift:926:30:926:33 | SSA def(x) | test.swift:927:12:927:12 | x |
| test.swift:926:30:926:33 | x | test.swift:926:30:926:33 | SSA def(x) |
| test.swift:926:45:926:48 | SSA def(y) | test.swift:928:12:928:12 | y |
| test.swift:926:45:926:48 | y | test.swift:926:45:926:48 | SSA def(y) |
| test.swift:927:12:927:21 | call to source() | test.swift:927:12:927:21 | OpenExistentialExpr |
| test.swift:929:12:929:35 | call to source() | test.swift:929:12:929:35 | OpenExistentialExpr |
| test.swift:927:12:927:31 | call to source(_:) | test.swift:927:12:927:31 | OpenExistentialExpr |
| test.swift:929:12:929:57 | call to source(_:) | test.swift:929:12:929:57 | OpenExistentialExpr |
12 changes: 6 additions & 6 deletions swift/ql/test/library-tests/dataflow/dataflow/test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -911,11 +911,11 @@ func autoclosureTest() {
// ---

protocol MyProtocol {
func source() -> Int
func source(_ label: String) -> Int
}

class MyProcotolImpl : MyProtocol {
func source() -> Int { return 0 }
func source(_ label: String) -> Int { return 0 }
}

func getMyProtocol() -> MyProtocol { return MyProcotolImpl() }
Expand All @@ -924,10 +924,10 @@ func getMyProtocolImpl() -> MyProcotolImpl { return MyProcotolImpl() }
func sink(arg: Int) { }

func testOpenExistentialExpr(x: MyProtocol, y: MyProcotolImpl) {
sink(arg: x.source()) // $ flow=927
sink(arg: y.source()) // $ flow=928
sink(arg: getMyProtocol().source()) // $ flow=929
sink(arg: getMyProtocolImpl().source()) // $ flow=930
sink(arg: x.source("x.source")) // $ flow=x.source
sink(arg: y.source("y.source")) // $ flow=y.source
sink(arg: getMyProtocol().source("getMyProtocol.source")) // $ flow=getMyProtocol.source
sink(arg: getMyProtocolImpl().source("getMyProtocolImpl.source")) // $ flow=getMyProtocolImpl.source
}

// ---
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
| conversions.swift:170:2:170:2 | self | conversions.swift:170:2:170:2 | SSA def(self) |
| conversions.swift:171:7:171:7 | SSA def(arr1) | conversions.swift:173:13:173:13 | arr1 |
| conversions.swift:171:7:171:7 | arr1 | conversions.swift:171:7:171:7 | SSA def(arr1) |
| conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:171:7:171:7 | arr1 |
| conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:171:7:171:7 | arr1 |
| conversions.swift:172:7:172:7 | SSA def(arr2) | conversions.swift:174:13:174:13 | arr2 |
| conversions.swift:172:7:172:7 | arr2 | conversions.swift:172:7:172:7 | SSA def(arr2) |
| conversions.swift:172:14:172:26 | [...] | conversions.swift:172:7:172:7 | arr2 |
Expand Down
22 changes: 11 additions & 11 deletions swift/ql/test/library-tests/dataflow/taint/core/Taint.expected
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ edges
| conversions.swift:156:25:156:69 | call to unsafeDowncast(_:to:) | conversions.swift:158:12:158:12 | v3 |
| conversions.swift:156:40:156:40 | parent | conversions.swift:156:25:156:69 | call to unsafeDowncast(_:to:) |
| conversions.swift:166:24:166:34 | call to sourceInt() | conversions.swift:166:12:166:35 | call to Self.init(_:) |
| conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:173:13:173:13 | arr1 |
| conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:175:13:175:19 | ...[...] |
| conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:178:25:178:25 | arr1 |
| conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:185:31:185:31 | arr1 |
| conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:173:13:173:13 | arr1 |
| conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:175:13:175:19 | ...[...] |
| conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:178:25:178:25 | arr1 |
| conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:185:31:185:31 | arr1 |
| conversions.swift:172:14:172:26 | [...] [Collection element] | conversions.swift:174:13:174:13 | arr2 |
| conversions.swift:172:14:172:26 | [...] [Collection element] | conversions.swift:176:13:176:13 | arr2 [Collection element] |
| conversions.swift:172:14:172:26 | [...] [Collection element] | conversions.swift:176:13:176:19 | ...[...] |
Expand Down Expand Up @@ -357,7 +357,7 @@ nodes
| conversions.swift:158:12:158:12 | v3 | semmle.label | v3 |
| conversions.swift:166:12:166:35 | call to Self.init(_:) | semmle.label | call to Self.init(_:) |
| conversions.swift:166:24:166:34 | call to sourceInt() | semmle.label | call to sourceInt() |
| conversions.swift:171:14:171:26 | call to sourceArray() | semmle.label | call to sourceArray() |
| conversions.swift:171:14:171:33 | call to sourceArray(_:) | semmle.label | call to sourceArray(_:) |
| conversions.swift:172:14:172:26 | [...] [Collection element] | semmle.label | [...] [Collection element] |
| conversions.swift:172:15:172:25 | call to sourceInt() | semmle.label | call to sourceInt() |
| conversions.swift:173:13:173:13 | arr1 | semmle.label | arr1 |
Expand Down Expand Up @@ -573,17 +573,17 @@ subpaths
| conversions.swift:157:12:157:12 | v3 | conversions.swift:152:31:152:44 | call to sourceString() | conversions.swift:157:12:157:12 | v3 | result |
| conversions.swift:158:12:158:12 | v3 | conversions.swift:152:31:152:44 | call to sourceString() | conversions.swift:158:12:158:12 | v3 | result |
| conversions.swift:166:12:166:35 | call to Self.init(_:) | conversions.swift:166:24:166:34 | call to sourceInt() | conversions.swift:166:12:166:35 | call to Self.init(_:) | result |
| conversions.swift:173:13:173:13 | arr1 | conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:173:13:173:13 | arr1 | result |
| conversions.swift:173:13:173:13 | arr1 | conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:173:13:173:13 | arr1 | result |
| conversions.swift:174:13:174:13 | arr2 | conversions.swift:172:15:172:25 | call to sourceInt() | conversions.swift:174:13:174:13 | arr2 | result |
| conversions.swift:175:13:175:19 | ...[...] | conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:175:13:175:19 | ...[...] | result |
| conversions.swift:175:13:175:19 | ...[...] | conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:175:13:175:19 | ...[...] | result |
| conversions.swift:176:13:176:19 | ...[...] | conversions.swift:172:15:172:25 | call to sourceInt() | conversions.swift:176:13:176:19 | ...[...] | result |
| conversions.swift:180:13:180:13 | arr1b | conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:180:13:180:13 | arr1b | result |
| conversions.swift:180:13:180:13 | arr1b | conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:180:13:180:13 | arr1b | result |
| conversions.swift:181:13:181:13 | arr2b | conversions.swift:172:15:172:25 | call to sourceInt() | conversions.swift:181:13:181:13 | arr2b | result |
| conversions.swift:182:13:182:20 | ...[...] | conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:182:13:182:20 | ...[...] | result |
| conversions.swift:182:13:182:20 | ...[...] | conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:182:13:182:20 | ...[...] | result |
| conversions.swift:183:13:183:20 | ...[...] | conversions.swift:172:15:172:25 | call to sourceInt() | conversions.swift:183:13:183:20 | ...[...] | result |
| conversions.swift:187:13:187:13 | arr1c | conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:187:13:187:13 | arr1c | result |
| conversions.swift:187:13:187:13 | arr1c | conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:187:13:187:13 | arr1c | result |
| conversions.swift:188:13:188:13 | arr2c | conversions.swift:172:15:172:25 | call to sourceInt() | conversions.swift:188:13:188:13 | arr2c | result |
| conversions.swift:189:13:189:20 | ...[...] | conversions.swift:171:14:171:26 | call to sourceArray() | conversions.swift:189:13:189:20 | ...[...] | result |
| conversions.swift:189:13:189:20 | ...[...] | conversions.swift:171:14:171:33 | call to sourceArray(_:) | conversions.swift:189:13:189:20 | ...[...] | result |
| conversions.swift:190:13:190:20 | ...[...] | conversions.swift:172:15:172:25 | call to sourceInt() | conversions.swift:190:13:190:20 | ...[...] | result |
| simple.swift:12:13:12:24 | ... .+(_:_:) ... | simple.swift:12:17:12:24 | call to source() | simple.swift:12:13:12:24 | ... .+(_:_:) ... | result |
| simple.swift:13:13:13:24 | ... .+(_:_:) ... | simple.swift:13:13:13:20 | call to source() | simple.swift:13:13:13:24 | ... .+(_:_:) ... | result |
Expand Down
20 changes: 3 additions & 17 deletions swift/ql/test/library-tests/dataflow/taint/core/TaintInline.ql
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
import swift
import TestUtilities.InlineFlowTest
import Taint
import TestUtilities.InlineExpectationsTest

module TaintTest implements TestSig {
string getARelevantTag() { result = "tainted" }
string customTaintFlowTag() { result = "tainted" }

predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node source, DataFlow::Node sink, Expr sinkExpr |
TestFlow::flow(source, sink) and
sinkExpr = sink.asExpr() and
location = sinkExpr.getLocation() and
element = sinkExpr.toString() and
tag = "tainted" and
value = source.asExpr().getLocation().getStartLine().toString()
)
}
}

import MakeTest<TaintTest>
import FlowTest<NoFlowConfig, DefaultFlowConfig, defaultValueFlowTag/0, customTaintFlowTag/0>
Loading