Skip to content

Commit 17e0a9a

Browse files
committed
unified: Also use exprStep for type casts
1 parent e3a6dda commit 17e0a9a

3 files changed

Lines changed: 24 additions & 14 deletions

File tree

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ private class SwiftDataFlowPlugin extends DataFlowPlugin {
2121
expr1 = expr.getOperand() and
2222
expr2 = expr
2323
)
24+
or
25+
mustFlow = true and
26+
exists(TypeCastExpr expr |
27+
// Type-cast operators:
28+
// - "as": Safe upcast conversion
29+
// - "as?": Wrap in Optional<T> if cast succeeds
30+
// - "as!": Throw if cast fails
31+
//
32+
// Since we bypass Optional<T> content, we model all of these as must-flow steps.
33+
expr.getOperator().getValue() = ["as", "as?", "as!"] and
34+
expr1 = expr.getExpr() and
35+
expr2 = expr
36+
)
2437
}
2538

2639
override predicate step(BuilderNode node1, Step step, BuilderNode node2) {
@@ -49,19 +62,6 @@ private class SwiftDataFlowPlugin extends DataFlowPlugin {
4962
node2.isResultValue(expr)
5063
)
5164
or
52-
exists(TypeCastExpr expr |
53-
// Type-cast operators:
54-
// - "as": Safe upcast conversion
55-
// - "as?": Wrap in Optional<T> if cast succeeds
56-
// - "as!": Throw if cast fails
57-
//
58-
// Since we bypass Optional<T> content, we model all of these as value steps.
59-
expr.getOperator().getValue() = ["as", "as?", "as!"] and
60-
node1.isResultValue(expr.getExpr()) and
61-
step.value() and
62-
node2.isResultValue(expr)
63-
)
64-
or
6565
exists(NullCoalescingExpr expr |
6666
// We bypass Optional<T> content so we add value-flow out of both operands of "??"
6767
node1.isResultValue(expr.getAnOperand()) and

‎unified/ql/test/library-tests/dataflow/test.expected‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ edges
448448
| test.swift:253:30:253:44 | source(...) | test.swift:253:16:253:45 | ... .some(...) | provenance | |
449449
| test.swift:255:10:255:22 | getOptional(...) | test.swift:255:10:255:35 | ... ?? ... | provenance | |
450450
| test.swift:256:20:256:32 | getOptional(...) | test.swift:256:10:256:32 | ... ?? ... | provenance | |
451+
| test.swift:264:5:264:23 | ... .field | test.swift:264:6:264:16 | [post] TypeCastExpr [field] | provenance | |
452+
| test.swift:264:6:264:16 | [post] TypeCastExpr [field] | test.swift:265:10:265:12 | box [field] | provenance | |
453+
| test.swift:264:27:264:41 | source(...) | test.swift:264:5:264:23 | ... .field | provenance | |
454+
| test.swift:265:10:265:12 | box [field] | test.swift:265:10:265:18 | ... .field | provenance | |
451455
nodes
452456
| calls.swift:7:19:7:19 | x | semmle.label | x |
453457
| calls.swift:8:14:8:14 | x | semmle.label | x |
@@ -991,6 +995,11 @@ nodes
991995
| test.swift:255:10:255:35 | ... ?? ... | semmle.label | ... ?? ... |
992996
| test.swift:256:10:256:32 | ... ?? ... | semmle.label | ... ?? ... |
993997
| test.swift:256:20:256:32 | getOptional(...) | semmle.label | getOptional(...) |
998+
| test.swift:264:5:264:23 | ... .field | semmle.label | ... .field |
999+
| test.swift:264:6:264:16 | [post] TypeCastExpr [field] | semmle.label | [post] TypeCastExpr [field] |
1000+
| test.swift:264:27:264:41 | source(...) | semmle.label | source(...) |
1001+
| test.swift:265:10:265:12 | box [field] | semmle.label | box [field] |
1002+
| test.swift:265:10:265:18 | ... .field | semmle.label | ... .field |
9941003
subpaths
9951004
| calls.swift:31:17:31:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:31:10:31:31 | target(...) |
9961005
| calls.swift:32:17:32:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:32:10:32:31 | target(...) |
@@ -1142,3 +1151,4 @@ testFailures
11421151
| test.swift:247:14:247:14 | x | test.swift:242:30:242:44 | source(...) | test.swift:247:14:247:14 | x | $@ | test.swift:242:30:242:44 | source(...) | source(...) |
11431152
| test.swift:255:10:255:35 | ... ?? ... | test.swift:253:30:253:44 | source(...) | test.swift:255:10:255:35 | ... ?? ... | $@ | test.swift:253:30:253:44 | source(...) | source(...) |
11441153
| test.swift:256:10:256:32 | ... ?? ... | test.swift:253:30:253:44 | source(...) | test.swift:256:10:256:32 | ... ?? ... | $@ | test.swift:253:30:253:44 | source(...) | source(...) |
1154+
| test.swift:265:10:265:18 | ... .field | test.swift:264:27:264:41 | source(...) | test.swift:265:10:265:18 | ... .field | $@ | test.swift:264:27:264:41 | source(...) | source(...) |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,5 +262,5 @@ func t29() {
262262
}
263263
let box = Box()
264264
(box as! Box).field = source("t29.1")
265-
sink(box.field) // $ MISSING: hasValueFlow=t29.1
265+
sink(box.field) // $ hasValueFlow=t29.1
266266
}

0 commit comments

Comments
 (0)