Merge pull request #14761 from geoffw0/moderntest

Swift: Update the inline dataflow tests
This commit is contained in:
Geoffrey White
2023-11-13 14:59:08 +00:00
committed by GitHub
15 changed files with 142 additions and 181 deletions

View File

@@ -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
* }
* ```
*
@@ -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()
)
}
@@ -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()
)
}
}
@@ -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>
}

View File

@@ -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] |
@@ -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 ... |
@@ -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 |

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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 |

View File

@@ -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() }
@@ -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
}
// ---

View File

@@ -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 |

View File

@@ -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 | ...[...] |
@@ -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 |
@@ -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 |

View File

@@ -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>

View File

@@ -6,7 +6,7 @@ func sourceFloat() -> Float { 0.0 }
func sourceFloat80() -> Float80 { 0.0 }
func sourceDouble() -> Double { 0.0 }
func sourceString() -> String { "" }
func sourceArray() -> [Int] { [] }
func sourceArray(_ label: String) -> [Int] { [] }
func sink(arg: Any) { }
@@ -168,25 +168,25 @@ func testCEnum() {
class TestArrayConversion {
init() {
let arr1 = sourceArray()
let arr1 = sourceArray("init1")
let arr2 = [sourceInt()]
sink(arg: arr1) // $ tainted=171
sink(arg: arr1) // $ tainted=init1
sink(arg: arr2) // $ tainted=172
sink(arg: arr1[0]) // $ tainted=171
sink(arg: arr1[0]) // $ tainted=init1
sink(arg: arr2[0]) // $ tainted=172
let arr1b = try Array(arr1)
let arr2b = try Array(arr2)
sink(arg: arr1b) // $ tainted=171
sink(arg: arr1b) // $ tainted=init1
sink(arg: arr2b) // $ tainted=172
sink(arg: arr1b[0]) // $ tainted=171
sink(arg: arr1b[0]) // $ tainted=init1
sink(arg: arr2b[0]) // $ tainted=172
let arr1c = ContiguousArray(arr1)
let arr2c = ContiguousArray(arr2)
sink(arg: arr1c) // $ tainted=171
sink(arg: arr1c) // $ tainted=init1
sink(arg: arr2c) // $ tainted=172
sink(arg: arr1c[0]) // $ tainted=171
sink(arg: arr1c[0]) // $ tainted=init1
sink(arg: arr2c[0]) // $ tainted=172
}
}

View File

@@ -1,18 +0,0 @@
import swift
import codeql.swift.dataflow.TaintTracking
import codeql.swift.dataflow.DataFlow
module TestConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
src.asExpr().(CallExpr).getStaticTarget().getName().matches("source%")
}
predicate isSink(DataFlow::Node sink) {
exists(CallExpr sinkCall |
sinkCall.getStaticTarget().getName().matches("sink%") and
sinkCall.getAnArgument().getExpr() = sink.asExpr()
)
}
}
module TestFlow = TaintTracking::Global<TestConfiguration>;

View File

@@ -1,20 +1,5 @@
import swift
import Taint
import TestUtilities.InlineExpectationsTest
import TestUtilities.InlineFlowTest
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>

View File

@@ -3,38 +3,38 @@
// --- tests ---
func source() -> UInt8 { return 0; }
func source(_ label: String) -> UInt8 { return 0; }
func source2() -> Int { return 0; }
func sink(arg: Any) {}
func taintThroughClosurePointer() {
var myArray1: [UInt8] = [1, 2, 3, 4]
myArray1[0] = source()
sink(arg: myArray1) // $ tainted=13
sink(arg: myArray1[0]) // $ tainted=13
myArray1[0] = source("myArray1")
sink(arg: myArray1) // $ tainted=myArray1
sink(arg: myArray1[0]) // $ tainted=myArray1
let return1 = myArray1.withUnsafeBytes({
ptr1 in
sink(arg: ptr1) // $ tainted=13
sink(arg: ptr1[0]) // $ tainted=13
return source()
sink(arg: ptr1) // $ tainted=myArray1
sink(arg: ptr1[0]) // $ tainted=myArray1
return source("return1")
})
sink(arg: return1) // $ tainted=20
sink(arg: return1) // $ tainted=return1
// ---
var myArray2: [UInt8] = [1, 2, 3, 4]
myArray2[0] = source()
sink(arg: myArray2) // $ tainted=28
sink(arg: myArray2[0]) // $ tainted=28
myArray2[0] = source("myArray2")
sink(arg: myArray2) // $ tainted=myArray2
sink(arg: myArray2[0]) // $ tainted=myArray2
let return2 = myArray2.withUnsafeBufferPointer({
ptr2 in
sink(arg: ptr2) // $ tainted=28
sink(arg: ptr2[0]) // $ tainted=28
return source()
sink(arg: ptr2) // $ tainted=myArray2
sink(arg: ptr2[0]) // $ tainted=myArray2
return source("return2")
})
sink(arg: return2) // $ tainted=35
sink(arg: return2) // $ tainted=return2
}
func taintThroughMutablePointer() {
@@ -44,15 +44,15 @@ func taintThroughMutablePointer() {
sink(arg: myArray1[0])
let return1 = myArray1.withUnsafeMutableBufferPointer({
buffer in
buffer.update(repeating: source())
sink(arg: buffer) // $ tainted=47
sink(arg: buffer[0]) // $ tainted=47
sink(arg: buffer.baseAddress!.pointee) // $ MISSING: tainted=47
return source()
buffer.update(repeating: source("array1write"))
sink(arg: buffer) // $ tainted=array1write
sink(arg: buffer[0]) // $ tainted=array1write
sink(arg: buffer.baseAddress!.pointee) // $ MISSING: tainted=array1write
return source("return1")
})
sink(arg: return1) // $ tainted=51
sink(arg: myArray1) // $ tainted=47
sink(arg: myArray1[0]) // $ tainted=47
sink(arg: return1) // $ tainted=return1
sink(arg: myArray1) // $ tainted=array1write
sink(arg: myArray1[0]) // $ tainted=array1write
// ---
@@ -62,15 +62,15 @@ func taintThroughMutablePointer() {
sink(arg: myArray2[0])
let return2 = myArray2.withUnsafeMutableBufferPointer({
buffer in
buffer.baseAddress!.pointee = source()
buffer.baseAddress!.pointee = source("array2write")
sink(arg: buffer)
sink(arg: buffer[0]) // $ MISSING: tainted=65
sink(arg: buffer.baseAddress!.pointee) // $ MISSING: tainted=65
return source()
sink(arg: buffer[0]) // $ MISSING: tainted=array2write
sink(arg: buffer.baseAddress!.pointee) // $ MISSING: tainted=array2write
return source("return2")
})
sink(arg: return2) // $ tainted=69
sink(arg: return2) // $ tainted=return2
sink(arg: myArray2)
sink(arg: myArray2[0]) // $ MISSING: tainted=65
sink(arg: myArray2[0]) // $ MISSING: tainted=array2write
// ---
@@ -80,44 +80,44 @@ func taintThroughMutablePointer() {
sink(arg: myArray3[0])
let return3 = myArray3.withContiguousMutableStorageIfAvailable({
ptr in
ptr.update(repeating: source())
sink(arg: ptr) // $ tainted=83
sink(arg: ptr[0]) // $ tainted=83
return source()
ptr.update(repeating: source("array3write"))
sink(arg: ptr) // $ tainted=array3write
sink(arg: ptr[0]) // $ tainted=array3write
return source("return3")
})
sink(arg: return3!) // $ tainted=86
sink(arg: myArray3) // $ tainted=83
sink(arg: myArray3[0]) // $ tainted=83
sink(arg: return3!) // $ tainted=return3
sink(arg: myArray3) // $ tainted=array3write
sink(arg: myArray3[0]) // $ tainted=array3write
// ---
var myArray4: [UInt8] = [1, 2, 3, 4]
var myArray5: [UInt8] = [5, 6, 7, 8]
myArray5[0] = source()
myArray5[0] = source("array5write")
sink(arg: myArray4)
sink(arg: myArray4[0])
sink(arg: myArray5) // $ tainted=97
sink(arg: myArray5[0]) // $ tainted=97
sink(arg: myArray5) // $ tainted=array5write
sink(arg: myArray5[0]) // $ tainted=array5write
let return4 = myArray4.withUnsafeMutableBytes({
ptr4 in
let return5 = myArray5.withUnsafeBytes({
ptr5 in
sink(arg: ptr5) // $ tainted=97
sink(arg: ptr5[0]) // $ tainted=97
sink(arg: ptr5) // $ tainted=array5write
sink(arg: ptr5[0]) // $ tainted=array5write
ptr4.copyBytes(from: ptr5)
sink(arg: ptr4)
sink(arg: ptr4[0]) // $ MISSING: tainted=97
return source()
sink(arg: ptr4[0]) // $ MISSING: tainted=array5write
return source("return5")
})
sink(arg: return5) // $ tainted=111
return source()
sink(arg: return5) // $ tainted=return5
return source("return4")
})
sink(arg: return4) // $ tainted=114
sink(arg: return4) // $ tainted=return4
sink(arg: myArray4)
sink(arg: myArray4[0]) // $ MISSING: tainted=97
sink(arg: myArray5) // $ tainted=97
sink(arg: myArray5[0]) // $ tainted=97
sink(arg: myArray4[0]) // $ MISSING: tainted=array5write
sink(arg: myArray5) // $ tainted=array5write
sink(arg: myArray5[0]) // $ tainted=array5write
// ---
@@ -131,9 +131,9 @@ func taintThroughMutablePointer() {
ptr.update(repeating: source2())
sink(arg: ptr) // $ tainted=131
sink(arg: ptr[0]) // $ tainted=131
return source()
return source("return6")
})
sink(arg: return6!) // $ tainted=134
sink(arg: return6!) // $ tainted=return6
sink(arg: myMutableBuffer) // $ tainted=131
sink(arg: myMutableBuffer[0]) // $ tainted=131
}