Skip to content

Commit 2c9433c

Browse files
authored
Merge pull request github#13946 from geoffw0/arraysteptest
Swift: Models and tests for numeric conversions
2 parents b1cee2f + ae15992 commit 2c9433c

22 files changed

+636
-11
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
5+
* Added taint models for `Numeric` conversions.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ private module Cached {
213213
// retaining this case increases robustness of flow).
214214
nodeFrom.asExpr() = nodeTo.asExpr().(ForceValueExpr).getSubExpr()
215215
or
216+
// read of an optional .some member via `let x: T = y: T?` pattern matching
217+
// note: similar to `ForceValueExpr` this is ideally a content `readStep` but
218+
// in practice we sometimes have taint on the optional itself.
219+
nodeTo.asPattern() = nodeFrom.asPattern().(OptionalSomePattern).getSubPattern()
220+
or
216221
// flow through `?` and `?.`
217222
nodeFrom.asExpr() = nodeTo.asExpr().(BindOptionalExpr).getSubExpr()
218223
or

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ private class ArraySummaries extends SummaryModelCsv {
1919
override predicate row(string row) {
2020
row =
2121
[
22+
";Array;true;init(_:);;;Argument[0];ReturnValue.CollectionElement;value",
23+
";Array;true;init(_:);;;Argument[0].CollectionElement;ReturnValue.CollectionElement;value",
24+
";Array;true;init(repeating:count:);;;Argument[0];ReturnValue.CollectionElement;value",
25+
";Array;true;init(arrayLiteral:);;;Argument[0].CollectionElement;ReturnValue.CollectionElement;value",
2226
";Array;true;insert(_:at:);;;Argument[0];Argument[-1].CollectionElement;value",
2327
";Array;true;insert(_:at:);;;Argument[1];Argument[-1];taint",
2428
";Array;true;withUnsafeBufferPointer(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint",

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CInterop.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ private import codeql.swift.dataflow.ExternalFlow
77

88
private class CInteropSummaries extends SummaryModelCsv {
99
override predicate row(string row) {
10-
row = ";;false;getVaList(_:);;;Argument[0].ArrayElement;ReturnValue;value"
10+
row = ";;false;getVaList(_:);;;Argument[0].CollectionElement;ReturnValue;value"
1111
}
1212
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Provides models for `Numeric` and related Swift classes (such as `Int` and `Float`).
3+
*/
4+
5+
import swift
6+
private import codeql.swift.dataflow.DataFlow
7+
private import codeql.swift.dataflow.ExternalFlow
8+
private import codeql.swift.dataflow.FlowSteps
9+
10+
/**
11+
* A model for `Numeric` and related class members and functions that permit taint flow.
12+
*/
13+
private class NumericSummaries extends SummaryModelCsv {
14+
override predicate row(string row) {
15+
row =
16+
[
17+
";;false;numericCast(_:);;;Argument[0];ReturnValue;taint",
18+
";;false;unsafeDowncast(_:to:);;;Argument[0];ReturnValue;taint",
19+
";;false;unsafeBitCast(_:to:);;;Argument[0];ReturnValue;taint",
20+
";Numeric;true;init(exactly:);;;Argument[0];ReturnValue.OptionalSome;value",
21+
";Numeric;true;init(bitPattern:);;;Argument[0];ReturnValue;taint",
22+
";BinaryInteger;true;init(_:);;;Argument[0];ReturnValue;taint",
23+
";BinaryInteger;true;init(clamping:);;;Argument[0];ReturnValue;taint",
24+
";BinaryInteger;true;init(truncatingIfNeeded:);;;Argument[0];ReturnValue;taint",
25+
";BinaryInteger;true;init(_:format:lenient:);;;Argument[0];ReturnValue;taint",
26+
";BinaryInteger;true;init(_:strategy:);;;Argument[0];ReturnValue;taint",
27+
";BinaryInteger;true;formatted();;;Argument[-1];ReturnValue;taint",
28+
";BinaryInteger;true;formatted(_:);;;Argument[-1];ReturnValue;taint",
29+
";FixedWidthInteger;true;init(_:radix:);;;Argument[0];ReturnValue;taint",
30+
";FixedWidthInteger;true;init(littleEndian:);;;Argument[0];ReturnValue;taint",
31+
";FixedWidthInteger;true;init(bigEndian:);;;Argument[0];ReturnValue;taint",
32+
";FloatingPoint;true;init(_:);;;Argument[0];ReturnValue;taint",
33+
";FloatingPoint;true;init(sign:exponent:significand:);;;Argument[1..2];ReturnValue;taint",
34+
";FloatingPoint;true;init(signOf:magnitudeOf:);;;Argument[1];ReturnValue;taint",
35+
]
36+
}
37+
}
38+
39+
/**
40+
* A content implying that, if a `Numeric` is tainted, then some of its fields are
41+
* tainted.
42+
*/
43+
private class NumericFieldsInheritTaint extends TaintInheritingContent,
44+
DataFlow::Content::FieldContent
45+
{
46+
NumericFieldsInheritTaint() {
47+
this.getField().hasQualifiedName("FixedWidthInteger", ["littleEndian", "bigEndian"])
48+
or
49+
this.getField()
50+
.hasQualifiedName(["Double", "Float", "Float80", "FloatingPoint"],
51+
["exponent", "significand"])
52+
}
53+
}

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ private import NsData
1515
private import NsObject
1616
private import NsString
1717
private import NsUrl
18+
private import Numeric
1819
private import PointerTypes
1920
private import Sequence
2021
private import Set

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ private class StringSource extends SourceModelCsv {
2727
}
2828

2929
/**
30-
* A model for `String` and `StringProtocol` members that permit taint flow.
30+
* A model for members of `String`, `StringProtocol` and similar classes that permit taint flow.
3131
*/
3232
private class StringSummaries extends SummaryModelCsv {
3333
override predicate row(string row) {
@@ -124,7 +124,8 @@ private class StringSummaries extends SummaryModelCsv {
124124
";String;true;randomElement();;;Argument[-1];ReturnValue;taint",
125125
";String;true;randomElement(using:);;;Argument[-1];ReturnValue;taint",
126126
";String;true;enumerated();;;Argument[-1];ReturnValue;taint",
127-
";String;true;encode(to:);;;Argument[-1];Argument[0];taint"
127+
";String;true;encode(to:);;;Argument[-1];Argument[0];taint",
128+
";LosslessStringConvertible;true;init(_:);;;Argument[0];ReturnValue;taint",
128129
]
129130
}
130131
}

swift/ql/lib/codeql/swift/security/CommandInjectionExtensions.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,13 @@ private class CommandInjectionSinks extends SinkModelCsv {
6969
]
7070
}
7171
}
72+
73+
/**
74+
* A barrier for command injection vulnerabilities.
75+
*/
76+
private class CommandInjectionDefaultBarrier extends CommandInjectionBarrier {
77+
CommandInjectionDefaultBarrier() {
78+
// any numeric type
79+
this.asExpr().getType().getUnderlyingType().getABaseType*().getName() = "Numeric"
80+
}
81+
}

swift/ql/lib/codeql/swift/security/PredicateInjectionExtensions.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,13 @@ private class PredicateInjectionSinkCsv extends SinkModelCsv {
3939
]
4040
}
4141
}
42+
43+
/**
44+
* A barrier for predicate injection vulnerabilities vulnerabilities.
45+
*/
46+
private class PredicateInjectionDefaultBarrier extends PredicateInjectionBarrier {
47+
PredicateInjectionDefaultBarrier() {
48+
// any numeric type
49+
this.asExpr().getType().getUnderlyingType().getABaseType*().getName() = "Numeric"
50+
}
51+
}

swift/ql/lib/codeql/swift/security/SqlInjectionExtensions.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,13 @@ private class GrdbDefaultSqlInjectionSink extends SqlInjectionSink {
153153
private class DefaultSqlInjectionSink extends SqlInjectionSink {
154154
DefaultSqlInjectionSink() { sinkNode(this, "sql-injection") }
155155
}
156+
157+
/**
158+
* A barrier for SQL injection.
159+
*/
160+
private class SqlInjectionDefaultBarrier extends SqlInjectionBarrier {
161+
SqlInjectionDefaultBarrier() {
162+
// any numeric type
163+
this.asExpr().getType().getUnderlyingType().getABaseType*().getName() = "Numeric"
164+
}
165+
}

0 commit comments

Comments
 (0)