Skip to content

Commit 27ec362

Browse files
committed
Swift: Understand binary pointwise operations.
1 parent ec2c58b commit 27ec362

File tree

8 files changed

+128
-14
lines changed

8 files changed

+128
-14
lines changed

swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ private module Cached {
4646
// allow flow through arithmetic (this case includes string concatenation)
4747
nodeTo.asExpr().(ArithmeticOperation).getAnOperand() = nodeFrom.asExpr()
4848
or
49+
// allow flow through bitwise operations
50+
nodeTo.asExpr().(BitwiseOperation).getAnOperand() = nodeFrom.asExpr()
51+
or
4952
// allow flow through assignment operations (e.g. `+=`)
5053
exists(AssignOperation op |
5154
nodeFrom.asExpr() = op.getSource() and

swift/ql/lib/codeql/swift/elements/expr/BitwiseOperation.qll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ private import codeql.swift.elements.expr.PrefixUnaryExpr
66
* A bitwise operation, such as:
77
* ```
88
* a & b
9+
* a << b
10+
* ~a
911
* ```
1012
*/
1113
class BitwiseOperation extends Expr {
@@ -27,13 +29,18 @@ class BitwiseOperation extends Expr {
2729
* A binary bitwise operation, such as:
2830
* ```
2931
* a & b
32+
* a << b
33+
* a .^ b
3034
* ```
3135
*/
3236
class BinaryBitwiseOperation extends BinaryExpr {
3337
BinaryBitwiseOperation() {
3438
this instanceof AndBitwiseExpr or
3539
this instanceof OrBitwiseExpr or
3640
this instanceof XorBitwiseExpr or
41+
this instanceof PointwiseAndExpr or
42+
this instanceof PointwiseOrExpr or
43+
this instanceof PointwiseXorExpr or
3744
this instanceof ShiftLeftBitwiseExpr or
3845
this instanceof ShiftRightBitwiseExpr
3946
}
@@ -69,6 +76,36 @@ class XorBitwiseExpr extends BinaryExpr {
6976
XorBitwiseExpr() { this.getStaticTarget().getName() = "^(_:_:)" }
7077
}
7178

79+
/**
80+
* A pointwise bitwise-and expression:
81+
* ```
82+
* a .& b
83+
* ```
84+
*/
85+
class PointwiseAndExpr extends BinaryExpr {
86+
PointwiseAndExpr() { this.getOperator().getName() = ".&(_:_:)" }
87+
}
88+
89+
/**
90+
* A pointwise bitwise-or expression:
91+
* ```
92+
* a .| b
93+
* ```
94+
*/
95+
class PointwiseOrExpr extends BinaryExpr {
96+
PointwiseOrExpr() { this.getOperator().getName() = ".|(_:_:)" }
97+
}
98+
99+
/**
100+
* A pointwise bitwise exclusive-or expression:
101+
* ```
102+
* a .^ b
103+
* ```
104+
*/
105+
class PointwiseXorExpr extends BinaryExpr {
106+
PointwiseXorExpr() { this.getOperator().getName() = ".^(_:_:)" }
107+
}
108+
72109
/**
73110
* A bitwise shift left expression.
74111
* ```

swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,27 @@
101101
| simple.swift:68:3:68:3 | [post] &... | simple.swift:69:13:69:13 | e |
102102
| simple.swift:68:3:68:3 | e | simple.swift:68:3:68:3 | &... |
103103
| simple.swift:68:8:68:8 | 100 | simple.swift:68:3:68:3 | &... |
104+
| simple.swift:73:13:73:13 | 0 | simple.swift:73:13:73:24 | ... .\|(_:_:) ... |
105+
| simple.swift:73:17:73:24 | call to source() | simple.swift:73:13:73:24 | ... .\|(_:_:) ... |
106+
| simple.swift:74:13:74:20 | call to source() | simple.swift:74:13:74:24 | ... .\|(_:_:) ... |
107+
| simple.swift:74:24:74:24 | 0 | simple.swift:74:13:74:24 | ... .\|(_:_:) ... |
108+
| simple.swift:76:13:76:13 | 0xffff | simple.swift:76:13:76:29 | ... .&(_:_:) ... |
109+
| simple.swift:76:22:76:29 | call to source() | simple.swift:76:13:76:29 | ... .&(_:_:) ... |
110+
| simple.swift:77:13:77:20 | call to source() | simple.swift:77:13:77:24 | ... .&(_:_:) ... |
111+
| simple.swift:77:24:77:24 | 0xffff | simple.swift:77:13:77:24 | ... .&(_:_:) ... |
112+
| simple.swift:79:13:79:13 | 0xffff | simple.swift:79:13:79:29 | ... .^(_:_:) ... |
113+
| simple.swift:79:22:79:29 | call to source() | simple.swift:79:13:79:29 | ... .^(_:_:) ... |
114+
| simple.swift:80:13:80:20 | call to source() | simple.swift:80:13:80:24 | ... .^(_:_:) ... |
115+
| simple.swift:80:24:80:24 | 0xffff | simple.swift:80:13:80:24 | ... .^(_:_:) ... |
116+
| simple.swift:82:13:82:20 | call to source() | simple.swift:82:13:82:25 | ... .<<(_:_:) ... |
117+
| simple.swift:82:25:82:25 | 1 | simple.swift:82:13:82:25 | ... .<<(_:_:) ... |
118+
| simple.swift:83:13:83:20 | call to source() | simple.swift:83:13:83:26 | ... .&<<(_:_:) ... |
119+
| simple.swift:83:26:83:26 | 1 | simple.swift:83:13:83:26 | ... .&<<(_:_:) ... |
120+
| simple.swift:84:13:84:20 | call to source() | simple.swift:84:13:84:25 | ... .>>(_:_:) ... |
121+
| simple.swift:84:25:84:25 | 1 | simple.swift:84:13:84:25 | ... .>>(_:_:) ... |
122+
| simple.swift:85:13:85:20 | call to source() | simple.swift:85:13:85:26 | ... .&>>(_:_:) ... |
123+
| simple.swift:85:26:85:26 | 1 | simple.swift:85:13:85:26 | ... .&>>(_:_:) ... |
124+
| simple.swift:87:14:87:21 | call to source() | simple.swift:87:13:87:21 | call to ~(_:) |
104125
| subscript.swift:1:7:1:7 | SSA def(self) | subscript.swift:1:7:1:7 | self[return] |
105126
| subscript.swift:1:7:1:7 | SSA def(self) | subscript.swift:1:7:1:7 | self[return] |
106127
| subscript.swift:1:7:1:7 | self | subscript.swift:1:7:1:7 | SSA def(self) |

swift/ql/test/library-tests/dataflow/taint/core/Taint.expected

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ edges
2626
| simple.swift:60:8:60:15 | call to source() : | simple.swift:63:13:63:13 | d |
2727
| simple.swift:66:8:66:15 | call to source() : | simple.swift:67:13:67:13 | e |
2828
| simple.swift:66:8:66:15 | call to source() : | simple.swift:69:13:69:13 | e |
29+
| simple.swift:73:17:73:24 | call to source() : | simple.swift:73:13:73:24 | ... .\|(_:_:) ... |
30+
| simple.swift:74:13:74:20 | call to source() : | simple.swift:74:13:74:24 | ... .\|(_:_:) ... |
31+
| simple.swift:76:22:76:29 | call to source() : | simple.swift:76:13:76:29 | ... .&(_:_:) ... |
32+
| simple.swift:77:13:77:20 | call to source() : | simple.swift:77:13:77:24 | ... .&(_:_:) ... |
33+
| simple.swift:79:22:79:29 | call to source() : | simple.swift:79:13:79:29 | ... .^(_:_:) ... |
34+
| simple.swift:80:13:80:20 | call to source() : | simple.swift:80:13:80:24 | ... .^(_:_:) ... |
35+
| simple.swift:82:13:82:20 | call to source() : | simple.swift:82:13:82:25 | ... .<<(_:_:) ... |
36+
| simple.swift:83:13:83:20 | call to source() : | simple.swift:83:13:83:26 | ... .&<<(_:_:) ... |
37+
| simple.swift:84:13:84:20 | call to source() : | simple.swift:84:13:84:25 | ... .>>(_:_:) ... |
38+
| simple.swift:85:13:85:20 | call to source() : | simple.swift:85:13:85:26 | ... .&>>(_:_:) ... |
39+
| simple.swift:87:14:87:21 | call to source() : | simple.swift:87:13:87:21 | call to ~(_:) |
2940
| subscript.swift:13:15:13:22 | call to source() : | subscript.swift:13:15:13:25 | ...[...] |
3041
| subscript.swift:14:15:14:23 | call to source2() : | subscript.swift:14:15:14:26 | ...[...] |
3142
| try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... |
@@ -81,6 +92,28 @@ nodes
8192
| simple.swift:66:8:66:15 | call to source() : | semmle.label | call to source() : |
8293
| simple.swift:67:13:67:13 | e | semmle.label | e |
8394
| simple.swift:69:13:69:13 | e | semmle.label | e |
95+
| simple.swift:73:13:73:24 | ... .\|(_:_:) ... | semmle.label | ... .\|(_:_:) ... |
96+
| simple.swift:73:17:73:24 | call to source() : | semmle.label | call to source() : |
97+
| simple.swift:74:13:74:20 | call to source() : | semmle.label | call to source() : |
98+
| simple.swift:74:13:74:24 | ... .\|(_:_:) ... | semmle.label | ... .\|(_:_:) ... |
99+
| simple.swift:76:13:76:29 | ... .&(_:_:) ... | semmle.label | ... .&(_:_:) ... |
100+
| simple.swift:76:22:76:29 | call to source() : | semmle.label | call to source() : |
101+
| simple.swift:77:13:77:20 | call to source() : | semmle.label | call to source() : |
102+
| simple.swift:77:13:77:24 | ... .&(_:_:) ... | semmle.label | ... .&(_:_:) ... |
103+
| simple.swift:79:13:79:29 | ... .^(_:_:) ... | semmle.label | ... .^(_:_:) ... |
104+
| simple.swift:79:22:79:29 | call to source() : | semmle.label | call to source() : |
105+
| simple.swift:80:13:80:20 | call to source() : | semmle.label | call to source() : |
106+
| simple.swift:80:13:80:24 | ... .^(_:_:) ... | semmle.label | ... .^(_:_:) ... |
107+
| simple.swift:82:13:82:20 | call to source() : | semmle.label | call to source() : |
108+
| simple.swift:82:13:82:25 | ... .<<(_:_:) ... | semmle.label | ... .<<(_:_:) ... |
109+
| simple.swift:83:13:83:20 | call to source() : | semmle.label | call to source() : |
110+
| simple.swift:83:13:83:26 | ... .&<<(_:_:) ... | semmle.label | ... .&<<(_:_:) ... |
111+
| simple.swift:84:13:84:20 | call to source() : | semmle.label | call to source() : |
112+
| simple.swift:84:13:84:25 | ... .>>(_:_:) ... | semmle.label | ... .>>(_:_:) ... |
113+
| simple.swift:85:13:85:20 | call to source() : | semmle.label | call to source() : |
114+
| simple.swift:85:13:85:26 | ... .&>>(_:_:) ... | semmle.label | ... .&>>(_:_:) ... |
115+
| simple.swift:87:13:87:21 | call to ~(_:) | semmle.label | call to ~(_:) |
116+
| simple.swift:87:14:87:21 | call to source() : | semmle.label | call to source() : |
84117
| subscript.swift:13:15:13:22 | call to source() : | semmle.label | call to source() : |
85118
| subscript.swift:13:15:13:25 | ...[...] | semmle.label | ...[...] |
86119
| subscript.swift:14:15:14:23 | call to source2() : | semmle.label | call to source2() : |
@@ -120,6 +153,17 @@ subpaths
120153
| simple.swift:63:13:63:13 | d | simple.swift:60:8:60:15 | call to source() : | simple.swift:63:13:63:13 | d | result |
121154
| simple.swift:67:13:67:13 | e | simple.swift:66:8:66:15 | call to source() : | simple.swift:67:13:67:13 | e | result |
122155
| simple.swift:69:13:69:13 | e | simple.swift:66:8:66:15 | call to source() : | simple.swift:69:13:69:13 | e | result |
156+
| simple.swift:73:13:73:24 | ... .\|(_:_:) ... | simple.swift:73:17:73:24 | call to source() : | simple.swift:73:13:73:24 | ... .\|(_:_:) ... | result |
157+
| simple.swift:74:13:74:24 | ... .\|(_:_:) ... | simple.swift:74:13:74:20 | call to source() : | simple.swift:74:13:74:24 | ... .\|(_:_:) ... | result |
158+
| simple.swift:76:13:76:29 | ... .&(_:_:) ... | simple.swift:76:22:76:29 | call to source() : | simple.swift:76:13:76:29 | ... .&(_:_:) ... | result |
159+
| simple.swift:77:13:77:24 | ... .&(_:_:) ... | simple.swift:77:13:77:20 | call to source() : | simple.swift:77:13:77:24 | ... .&(_:_:) ... | result |
160+
| simple.swift:79:13:79:29 | ... .^(_:_:) ... | simple.swift:79:22:79:29 | call to source() : | simple.swift:79:13:79:29 | ... .^(_:_:) ... | result |
161+
| simple.swift:80:13:80:24 | ... .^(_:_:) ... | simple.swift:80:13:80:20 | call to source() : | simple.swift:80:13:80:24 | ... .^(_:_:) ... | result |
162+
| simple.swift:82:13:82:25 | ... .<<(_:_:) ... | simple.swift:82:13:82:20 | call to source() : | simple.swift:82:13:82:25 | ... .<<(_:_:) ... | result |
163+
| simple.swift:83:13:83:26 | ... .&<<(_:_:) ... | simple.swift:83:13:83:20 | call to source() : | simple.swift:83:13:83:26 | ... .&<<(_:_:) ... | result |
164+
| simple.swift:84:13:84:25 | ... .>>(_:_:) ... | simple.swift:84:13:84:20 | call to source() : | simple.swift:84:13:84:25 | ... .>>(_:_:) ... | result |
165+
| simple.swift:85:13:85:26 | ... .&>>(_:_:) ... | simple.swift:85:13:85:20 | call to source() : | simple.swift:85:13:85:26 | ... .&>>(_:_:) ... | result |
166+
| simple.swift:87:13:87:21 | call to ~(_:) | simple.swift:87:14:87:21 | call to source() : | simple.swift:87:13:87:21 | call to ~(_:) | result |
123167
| subscript.swift:13:15:13:25 | ...[...] | subscript.swift:13:15:13:22 | call to source() : | subscript.swift:13:15:13:25 | ...[...] | result |
124168
| subscript.swift:14:15:14:26 | ...[...] | subscript.swift:14:15:14:23 | call to source2() : | subscript.swift:14:15:14:26 | ...[...] | result |
125169
| try.swift:9:13:9:24 | try ... | try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... | result |

swift/ql/test/library-tests/dataflow/taint/core/simple.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,19 @@ func taintThroughAssignmentArithmetic() {
7070
}
7171

7272
func taintThroughBitwiseOperators() {
73-
sink(arg: 0 | source()) // $ MISSING: tainted=73
74-
sink(arg: source() | 0) // $ MISSING: tainted=74
73+
sink(arg: 0 | source()) // $ tainted=73
74+
sink(arg: source() | 0) // $ tainted=74
7575

76-
sink(arg: 0xffff & source()) // $ MISSING: tainted=76
77-
sink(arg: source() & 0xffff) // $ MISSING: tainted=77
76+
sink(arg: 0xffff & source()) // $ tainted=76
77+
sink(arg: source() & 0xffff) // $ tainted=77
7878

79-
sink(arg: 0xffff ^ source()) // $ MISSING: tainted=79
80-
sink(arg: source() ^ 0xffff) // $ MISSING: tainted=80
79+
sink(arg: 0xffff ^ source()) // $ tainted=79
80+
sink(arg: source() ^ 0xffff) // $ tainted=80
8181

82-
sink(arg: source() << 1) // $ MISSING: tainted=82
83-
sink(arg: source() &<< 1) // $ MISSING: tainted=83
84-
sink(arg: source() >> 1) // $ MISSING: tainted=84
85-
sink(arg: source() &>> 1) // $ MISSING: tainted=85
82+
sink(arg: source() << 1) // $ tainted=82
83+
sink(arg: source() &<< 1) // $ tainted=83
84+
sink(arg: source() >> 1) // $ tainted=84
85+
sink(arg: source() &>> 1) // $ tainted=85
8686

87-
sink(arg: ~source()) // $ MISSING: tainted=87
87+
sink(arg: ~source()) // $ tainted=87
8888
}

swift/ql/test/library-tests/elements/expr/bitwiseopration/bitwiseoperation.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
| bitwiseoperation.swift:7:7:7:12 | ... .>>(_:_:) ... | BinaryBitwiseOperation, ShiftRightBitwiseExpr |
77
| bitwiseoperation.swift:10:7:10:13 | ... .&<<(_:_:) ... | BinaryBitwiseOperation, ShiftLeftBitwiseExpr |
88
| bitwiseoperation.swift:11:7:11:13 | ... .&>>(_:_:) ... | BinaryBitwiseOperation, ShiftRightBitwiseExpr |
9+
| bitwiseoperation.swift:17:7:17:12 | ... ..&(_:_:) ... | BinaryBitwiseOperation, PointwiseAndExpr |
10+
| bitwiseoperation.swift:18:7:18:12 | ... ..\|(_:_:) ... | BinaryBitwiseOperation, PointwiseOrExpr |
11+
| bitwiseoperation.swift:19:7:19:12 | ... ..^(_:_:) ... | BinaryBitwiseOperation, PointwiseXorExpr |

swift/ql/test/library-tests/elements/expr/bitwiseopration/bitwiseoperation.ql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ string describe(BitwiseOperation e) {
99
or
1010
e instanceof XorBitwiseExpr and result = "XorBitwiseExpr"
1111
or
12+
e instanceof PointwiseAndExpr and result = "PointwiseAndExpr"
13+
or
14+
e instanceof PointwiseOrExpr and result = "PointwiseOrExpr"
15+
or
16+
e instanceof PointwiseXorExpr and result = "PointwiseXorExpr"
17+
or
1218
e instanceof ShiftLeftBitwiseExpr and result = "ShiftLeftBitwiseExpr"
1319
or
1420
e instanceof ShiftRightBitwiseExpr and result = "ShiftRightBitwiseExpr"

swift/ql/test/library-tests/elements/expr/bitwiseopration/bitwiseoperation.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func bitwise() {
1414
let a = SIMD4<Int>(1, 2, 3, 4)
1515
let b = SIMD4<Int>(4, 3, 2, 1)
1616
let m = a .< b
17-
_ = m .& m // NOT DETECTED
18-
_ = m .| m // NOT DETECTED
19-
_ = m .^ m // NOT DETECTED
17+
_ = m .& m
18+
_ = m .| m
19+
_ = m .^ m
2020
}

0 commit comments

Comments
 (0)