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
20 changes: 2 additions & 18 deletions swift/ql/test/library-tests/dataflow/dataflow/DataFlow.ql
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,10 @@
*/

import swift
import codeql.swift.dataflow.DataFlow
import codeql.swift.dataflow.DataFlow::DataFlow
import FlowConfig
import DataFlow::PathGraph

class TestConfiguration extends DataFlow::Configuration {
TestConfiguration() { this = "TestConfiguration" }

override predicate isSource(DataFlow::Node src) {
src.asExpr().(CallExpr).getStaticTarget().getName() = "source()"
}

override predicate isSink(DataFlow::Node sink) {
exists(CallExpr sinkCall |
sinkCall.getStaticTarget().getName() = "sink(arg:)" and
sinkCall.getAnArgument().getExpr() = sink.asExpr()
)
}

override int explorationLimit() { result = 100 }
}

from DataFlow::PathNode src, DataFlow::PathNode sink, TestConfiguration test
where test.hasFlowPath(src, sink)
select sink, src, sink, "result"
Empty file.
21 changes: 21 additions & 0 deletions swift/ql/test/library-tests/dataflow/dataflow/DataFlowInline.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import swift
import DataFlow
import FlowConfig
import TestUtilities.InlineExpectationsTest

class TaintTest extends InlineExpectationsTest {
TaintTest() { this = "DataFlowTest" }

override string getARelevantTag() { result = "flow" }

override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(TestConfiguration config, Node source, Node sink, Expr sinkExpr |
config.hasFlow(source, sink) and
sinkExpr = sink.asExpr() and
location = sinkExpr.getLocation() and
element = sinkExpr.toString() and
tag = "flow" and
value = source.asExpr().getLocation().getStartLine().toString()
)
}
}
23 changes: 23 additions & 0 deletions swift/ql/test/library-tests/dataflow/dataflow/FlowConfig.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @kind path-problem
*/

import swift
import codeql.swift.dataflow.DataFlow

class TestConfiguration extends DataFlow::Configuration {
TestConfiguration() { this = "TestConfiguration" }

override predicate isSource(DataFlow::Node src) {
src.asExpr().(CallExpr).getStaticTarget().getName() = "source()"
}

override predicate isSink(DataFlow::Node sink) {
exists(CallExpr sinkCall |
sinkCall.getStaticTarget().getName() = "sink(arg:)" and
sinkCall.getAnArgument().getExpr() = sink.asExpr()
)
}

override int explorationLimit() { result = 100 }
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
| file://:0:0:0:0 | .a | file://:0:0:0:0 | &... |
| file://:0:0:0:0 | .source_value | file://:0:0:0:0 | &... |
| file://:0:0:0:0 | .wrappedValue | file://:0:0:0:0 | &... |
| file://:0:0:0:0 | .x | file://:0:0:0:0 | &... |
| file://:0:0:0:0 | self | file://:0:0:0:0 | &... |
| file://:0:0:0:0 | self | file://:0:0:0:0 | &... |
| test.swift:6:9:6:13 | WriteDef | test.swift:7:15:7:15 | t1 |
| test.swift:6:19:6:26 | call to source() | test.swift:6:9:6:13 | WriteDef |
| test.swift:7:15:7:15 | t1 | test.swift:8:10:8:10 | t1 |
Expand Down Expand Up @@ -102,3 +108,35 @@
| test.swift:154:10:154:13 | WriteDef | test.swift:155:19:155:19 | i |
| test.swift:154:10:154:13 | i | test.swift:155:19:155:19 | i |
| test.swift:157:5:157:5 | lambdaSink | test.swift:159:5:159:5 | lambdaSink |
| test.swift:163:7:163:7 | WriteDef | file://:0:0:0:0 | value |
| test.swift:163:7:163:7 | value | file://:0:0:0:0 | value |
| test.swift:169:12:169:22 | WriteDef | test.swift:170:9:170:9 | value |
| test.swift:169:12:169:22 | value | test.swift:170:9:170:9 | value |
| test.swift:179:7:179:7 | WriteDef | test.swift:180:3:180:3 | a |
| test.swift:179:11:179:13 | call to init | test.swift:179:7:179:7 | WriteDef |
| test.swift:180:3:180:3 | a | test.swift:181:13:181:13 | a |
| test.swift:185:7:185:7 | WriteDef | file://:0:0:0:0 | value |
| test.swift:185:7:185:7 | value | file://:0:0:0:0 | value |
| test.swift:193:7:193:7 | WriteDef | test.swift:194:3:194:3 | b |
| test.swift:193:11:193:13 | call to init | test.swift:193:7:193:7 | WriteDef |
| test.swift:194:3:194:3 | b | test.swift:195:13:195:13 | b |
| test.swift:199:7:199:7 | WriteDef | test.swift:200:3:200:3 | a |
| test.swift:199:11:199:13 | call to init | test.swift:199:7:199:7 | WriteDef |
| test.swift:200:3:200:3 | a | test.swift:201:13:201:13 | a |
| test.swift:205:7:205:7 | WriteDef | test.swift:206:3:206:3 | a |
| test.swift:205:11:205:13 | call to init | test.swift:205:7:205:7 | WriteDef |
| test.swift:206:3:206:3 | a | test.swift:207:13:207:13 | a |
| test.swift:211:7:211:7 | WriteDef | test.swift:212:3:212:3 | a |
| test.swift:211:11:211:13 | call to init | test.swift:211:7:211:7 | WriteDef |
| test.swift:212:3:212:3 | a | test.swift:213:13:213:13 | a |
| test.swift:217:7:217:7 | WriteDef | test.swift:218:3:218:3 | b |
| test.swift:217:11:217:13 | call to init | test.swift:217:7:217:7 | WriteDef |
| test.swift:218:3:218:3 | b | test.swift:219:13:219:13 | b |
| test.swift:234:7:234:7 | WriteDef | test.swift:235:13:235:13 | a |
| test.swift:234:11:234:31 | call to init | test.swift:234:7:234:7 | WriteDef |
| test.swift:235:13:235:13 | a | test.swift:237:3:237:3 | a |
| test.swift:237:3:237:3 | a | test.swift:238:13:238:13 | a |
| test.swift:242:9:242:9 | WriteDef | file://:0:0:0:0 | value |
| test.swift:242:9:242:9 | value | file://:0:0:0:0 | value |
| test.swift:252:23:252:23 | WriteDef | file://:0:0:0:0 | value |
| test.swift:252:23:252:23 | value | file://:0:0:0:0 | value |
132 changes: 113 additions & 19 deletions swift/ql/test/library-tests/dataflow/dataflow/test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ func sink(arg: Int) {}
func intraprocedural_with_local_flow() -> Void {
var t2: Int
var t1: Int = source()
sink(arg: t1)
sink(arg: t1) // $ flow=6
t2 = t1
sink(arg: t1)
sink(arg: t2)
sink(arg: t1) // $ flow=6
sink(arg: t2) // $ flow=6
if(t1 != 0) {
t2 = 0
sink(arg: t2)
}
sink(arg: t2)
sink(arg: t2) // $ MISSING: flow=6

t1 = 0;
while(false) {
Expand All @@ -27,16 +27,16 @@ func caller_source() -> Void {
}

func callee_sink(x: Int, y: Int) -> Void {
sink(arg: x)
sink(arg: y)
sink(arg: x) // $ flow=25
sink(arg: y) // $ flow=26
}

func callee_source() -> Int {
return source()
}

func caller_sink() -> Void {
sink(arg: callee_source())
sink(arg: callee_source()) // $ flow=35
}

func branching(b: Bool) -> Void {
Expand All @@ -47,7 +47,7 @@ func branching(b: Bool) -> Void {
} else {
t = 1;
}
sink(arg: t)
sink(arg: t) // $ flow=43
}

func inoutSource(arg: inout Int) -> Void {
Expand All @@ -59,7 +59,7 @@ func inoutUser() {
var x: Int = 0
sink(arg: x)
inoutSource(arg: &x)
sink(arg: x)
sink(arg: x) // $ flow=54
}

func inoutSwap(arg1: inout Int, arg2: inout Int) -> Void {
Expand All @@ -73,8 +73,8 @@ func swapUser() {
var x: Int = source()
var y: Int = 0
inoutSwap(arg1: &x, arg2: &y)
sink(arg: x)
sink(arg: y)
sink(arg: x) // clean
sink(arg: y) // $ flow=73
}

func inoutSourceWithoutReturn(arg: inout Int) {
Expand All @@ -95,14 +95,14 @@ func inoutUser2(bool: Bool) {
var x: Int = 0
sink(arg: x) // clean
inoutSourceWithoutReturn(arg: &x)
sink(arg: x) // tainted
sink(arg: x) // $ flow=81
}

do {
var x: Int = 0
sink(arg: x) // clean
inoutSourceMultipleReturn(arg: &x, bool: bool)
sink(arg: x) // tainted by two sources
sink(arg: x) // $ flow=86 flow=89
}
}

Expand All @@ -117,13 +117,13 @@ func forward(arg: Int, lambda: (Int) -> Int) -> Int {
func forwarder() {
var x: Int = source()
var y: Int = forward(arg: x, lambda: id)
sink(arg: y)
sink(arg: y) // $ flow=118

var z: Int = forward(arg: source(), lambda: {
(i: Int) -> Int in
return i
})
sink(arg: z)
sink(arg: z) // $ flow=122

var clean: Int = forward(arg: source(), lambda: {
(i: Int) -> Int in
Expand All @@ -135,26 +135,120 @@ func forwarder() {
func lambdaFlows() {
var lambda1 = {
() -> Void in
sink(arg: source())
sink(arg: source()) // $ flow=138
}

var lambda2 = {
(i: Int) -> Int in
return i
}
sink(arg: lambda2(source()))
sink(arg: lambda2(source())) // $ flow=145

var lambdaSource = {
() -> Int in
return source()
}
sink(arg: lambdaSource())
sink(arg: lambdaSource()) // $ flow=149

var lambdaSink = {
(i: Int) -> Void in
sink(arg: i)
sink(arg: i) // $ flow=157 flow=149
}
lambdaSink(source())

lambdaSink(lambdaSource())
}

class A {
var x : Int

init() {
x = 0
}

func set(_ value : Int) {
x = value
}

func get() -> Int {
return x
}
}

func simple_field_flow() {
var a = A()
a.x = source()
sink(arg: a.x) // $ MISSING: flow=180
}

class B {
var a : A

init() {
a = A()
}
}

func reverse_read() {
var b = B()
b.a.x = source()
sink(arg: b.a.x) // $ MISSING: flow=194
}

func test_setter() {
var a = A()
a.set(source())
sink(arg: a.x) // $ MISSING: flow=200
}

func test_getter() {
var a = A()
a.x = source()
sink(arg: a.get()) // $ MISSING: flow=206
}

func test_setter_getter() {
var a = A()
a.set(source())
sink(arg: a.get()) // $ MISSING: flow=212
}

func flow_through(b : B) {
var b = B()
b.a.set(source())
sink(arg: b.a.x) // $ MISSING: flow=218
}

class HasComputedProperty {
var source_value : Int {
get {
return source()
}
set {

}
}
}

func test_computed_property() {
var a = HasComputedProperty()
sink(arg: a.source_value) // $ MISSING: flow=225

a.source_value = 0
sink(arg: a.source_value) // $ MISSING: flow=225
}

@propertyWrapper struct DidSetSource {
var wrappedValue: Int {
didSet { wrappedValue = source() }
}

init(wrappedValue: Int) {
self.wrappedValue = 0
}
}

func test_property_wrapper() {
@DidSetSource var x = 42
sink(arg: x) // $ MISSING: flow=243
}