@@ -7,13 +7,14 @@ import swift
7
7
import codeql.swift.dataflow.DataFlow
8
8
9
9
/**
10
- * A flow state for encoding types of Swift string encoding.
10
+ * A type of Swift string encoding. This class is used as a flow state for
11
+ * the string length conflation taint tracking configuration.
11
12
*/
12
- class StringLengthConflationFlowState extends string {
13
- string equivClass ;
13
+ class StringType extends string {
14
14
string singular ;
15
+ string equivClass ;
15
16
16
- StringLengthConflationFlowState ( ) {
17
+ StringType ( ) {
17
18
this = "String" and singular = "a String" and equivClass = "String"
18
19
or
19
20
this = "NSString" and singular = "an NSString" and equivClass = "NSString"
@@ -38,3 +39,159 @@ class StringLengthConflationFlowState extends string {
38
39
*/
39
40
string getSingular ( ) { result = singular }
40
41
}
42
+
43
+ /**
44
+ * A dataflow source for string length conflation vulnerabilities. That is,
45
+ * a `DataFlow::Node` where a string length is generated.
46
+ */
47
+ abstract class StringLengthConflationSource extends DataFlow:: Node {
48
+ /**
49
+ * Gets the `StringType` for this source.
50
+ */
51
+ abstract StringType getStringType ( ) ;
52
+ }
53
+
54
+ /**
55
+ * A dataflow sink for string length conflation vulnerabilities. That is,
56
+ * a `DataFlow::Node` where a string length is used.
57
+ */
58
+ abstract class StringLengthConflationSink extends DataFlow:: Node {
59
+ /**
60
+ * Gets the correct `StringType` for this sink.
61
+ */
62
+ abstract StringType getCorrectStringType ( ) ;
63
+ }
64
+
65
+ abstract class StringLengthConflationSanitizer extends DataFlow:: Node { }
66
+
67
+ /**
68
+ * A unit class for adding additional taint steps.
69
+ */
70
+ class StringLengthConflationAdditionalTaintStep extends Unit {
71
+ /**
72
+ * Holds if the step from `node1` to `node2` should be considered a taint
73
+ * step for paths related to string length conflation vulnerabilities.
74
+ */
75
+ abstract predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) ;
76
+ }
77
+
78
+ private class DefaultStringLengthConflationSource extends StringLengthConflationSource {
79
+ StringType stringType ;
80
+
81
+ DefaultStringLengthConflationSource ( ) {
82
+ exists ( MemberRefExpr memberRef , string className , string varName |
83
+ memberRef .getBase ( ) .getType ( ) .( NominalType ) .getABaseType * ( ) .getName ( ) = className and
84
+ memberRef .getMember ( ) .( VarDecl ) .getName ( ) = varName and
85
+ this .asExpr ( ) = memberRef and
86
+ (
87
+ // result of a call to `String.count`
88
+ className = "String" and
89
+ varName = "count" and
90
+ stringType = "String"
91
+ or
92
+ // result of a call to `NSString.length`
93
+ className = [ "NSString" , "NSMutableString" ] and
94
+ varName = "length" and
95
+ stringType = "NSString"
96
+ or
97
+ // result of a call to `String.utf8.count`
98
+ className = "String.UTF8View" and
99
+ varName = "count" and
100
+ stringType = "String.utf8"
101
+ or
102
+ // result of a call to `String.utf16.count`
103
+ className = "String.UTF16View" and
104
+ varName = "count" and
105
+ stringType = "String.utf16"
106
+ or
107
+ // result of a call to `String.unicodeScalars.count`
108
+ className = "String.UnicodeScalarView" and
109
+ varName = "count" and
110
+ stringType = "String.unicodeScalars"
111
+ )
112
+ )
113
+ }
114
+
115
+ override StringType getStringType ( ) { result = stringType }
116
+ }
117
+
118
+ private class DefaultStringLengthConflationSink extends StringLengthConflationSink {
119
+ StringType correctStringType ;
120
+
121
+ DefaultStringLengthConflationSink ( ) {
122
+ exists ( AbstractFunctionDecl funcDecl , CallExpr call , string funcName , int arg |
123
+ (
124
+ // arguments to method calls...
125
+ exists ( string className , ClassOrStructDecl c |
126
+ (
127
+ // `NSRange.init`
128
+ className = "NSRange" and
129
+ funcName = "init(location:length:)" and
130
+ arg = [ 0 , 1 ]
131
+ or
132
+ // `NSString.character`
133
+ className = [ "NSString" , "NSMutableString" ] and
134
+ funcName = "character(at:)" and
135
+ arg = 0
136
+ or
137
+ // `NSString.character`
138
+ className = [ "NSString" , "NSMutableString" ] and
139
+ funcName = "substring(from:)" and
140
+ arg = 0
141
+ or
142
+ // `NSString.character`
143
+ className = [ "NSString" , "NSMutableString" ] and
144
+ funcName = "substring(to:)" and
145
+ arg = 0
146
+ or
147
+ // `NSMutableString.insert`
148
+ className = "NSMutableString" and
149
+ funcName = "insert(_:at:)" and
150
+ arg = 1
151
+ ) and
152
+ c .getName ( ) = className and
153
+ c .getABaseTypeDecl * ( ) .( ClassOrStructDecl ) .getAMember ( ) = funcDecl and
154
+ call .getStaticTarget ( ) = funcDecl and
155
+ correctStringType = "NSString"
156
+ )
157
+ or
158
+ // arguments to function calls...
159
+ // `NSMakeRange`
160
+ funcName = "NSMakeRange(_:_:)" and
161
+ arg = [ 0 , 1 ] and
162
+ call .getStaticTarget ( ) = funcDecl and
163
+ correctStringType = "NSString"
164
+ or
165
+ // arguments to method calls...
166
+ (
167
+ // `String.dropFirst`, `String.dropLast`, `String.removeFirst`, `String.removeLast`
168
+ funcName = [ "dropFirst(_:)" , "dropLast(_:)" , "removeFirst(_:)" , "removeLast(_:)" ] and
169
+ arg = 0
170
+ or
171
+ // `String.prefix`, `String.suffix`
172
+ funcName = [ "prefix(_:)" , "suffix(_:)" ] and
173
+ arg = 0
174
+ or
175
+ // `String.Index.init`
176
+ funcName = "init(encodedOffset:)" and
177
+ arg = 0
178
+ or
179
+ // `String.index`
180
+ funcName = [ "index(_:offsetBy:)" , "index(_:offsetBy:limitBy:)" ] and
181
+ arg = [ 0 , 1 ]
182
+ or
183
+ // `String.formIndex`
184
+ funcName = [ "formIndex(_:offsetBy:)" , "formIndex(_:offsetBy:limitBy:)" ] and
185
+ arg = [ 0 , 1 ]
186
+ ) and
187
+ call .getStaticTarget ( ) = funcDecl and
188
+ correctStringType = "String"
189
+ ) and
190
+ // match up `funcName`, `arg`, `node`.
191
+ funcDecl .getName ( ) = funcName and
192
+ call .getArgument ( arg ) .getExpr ( ) = this .asExpr ( )
193
+ )
194
+ }
195
+
196
+ override StringType getCorrectStringType ( ) { result = correctStringType }
197
+ }
0 commit comments