@@ -14,6 +14,24 @@ import swift
14
14
import codeql.swift.dataflow.DataFlow
15
15
import DataFlow:: PathGraph
16
16
17
+ /**
18
+ * A flow state for this query, which is a type of Swift string encoding.
19
+ */
20
+ class StringLengthConflationFlowState extends string {
21
+ string singular ;
22
+
23
+ StringLengthConflationFlowState ( ) {
24
+ this = "String" and singular = "a String"
25
+ or
26
+ this = "NSString" and singular = "an NSString"
27
+ }
28
+
29
+ /**
30
+ * Gets text for the singular form of this flow state.
31
+ */
32
+ string getSingular ( ) { result = singular }
33
+ }
34
+
17
35
/**
18
36
* A configuration for tracking string lengths originating from source that is
19
37
* a `String` or an `NSString` object, to a sink of a different kind that
@@ -40,7 +58,11 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
40
58
)
41
59
}
42
60
43
- override predicate isSink ( DataFlow:: Node node , string flowstate ) {
61
+ /**
62
+ * Holds if `node` is a sink and `flowstate` is the *correct* flow state for
63
+ * that sink. We actually want to report incorrect flow states.
64
+ */
65
+ predicate isSinkImpl ( DataFlow:: Node node , string flowstate ) {
44
66
// arguments to method calls...
45
67
exists (
46
68
string className , string methodName , string paramName , ClassDecl c , AbstractFunctionDecl f ,
@@ -78,7 +100,7 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
78
100
f .getName ( ) = methodName and
79
101
f .getParam ( pragma [ only_bind_into ] ( arg ) ) .getName ( ) = paramName and
80
102
call .getArgument ( pragma [ only_bind_into ] ( arg ) ) .getExpr ( ) = node .asExpr ( ) and
81
- flowstate = "String" // `String` length flowing into ` NSString`
103
+ flowstate = "NSString"
82
104
)
83
105
or
84
106
// arguments to function calls...
@@ -89,7 +111,7 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
89
111
call .getStaticTarget ( ) .getName ( ) = funcName and
90
112
call .getStaticTarget ( ) .getParam ( pragma [ only_bind_into ] ( arg ) ) .getName ( ) = paramName and
91
113
call .getArgument ( pragma [ only_bind_into ] ( arg ) ) .getExpr ( ) = node .asExpr ( ) and
92
- flowstate = "String" // `String` length flowing into ` NSString`
114
+ flowstate = "NSString"
93
115
)
94
116
or
95
117
// arguments to function calls...
@@ -122,7 +144,16 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
122
144
.getParam ( pragma [ only_bind_into ] ( arg ) )
123
145
.getName ( ) = paramName and
124
146
call .getArgument ( pragma [ only_bind_into ] ( arg ) ) .getExpr ( ) = node .asExpr ( ) and
125
- flowstate = "NSString" // `NSString` length flowing into `String`
147
+ flowstate = "String"
148
+ )
149
+ }
150
+
151
+ override predicate isSink ( DataFlow:: Node node , string flowstate ) {
152
+ // Permit any *incorrect* flowstate, as those are the results the query
153
+ // should report.
154
+ exists ( string correctFlowState |
155
+ isSinkImpl ( node , correctFlowState ) and
156
+ flowstate .( StringLengthConflationFlowState ) != correctFlowState
126
157
)
127
158
}
128
159
@@ -134,15 +165,13 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
134
165
135
166
from
136
167
StringLengthConflationConfiguration config , DataFlow:: PathNode source , DataFlow:: PathNode sink ,
137
- string flowstate , string message
168
+ StringLengthConflationFlowState sourceFlowState , StringLengthConflationFlowState sinkFlowstate ,
169
+ string message
138
170
where
139
171
config .hasFlowPath ( source , sink ) and
140
- config .isSink ( sink .getNode ( ) , flowstate ) and
141
- (
142
- flowstate = "String" and
143
- message = "This String length is used in an NSString, but it may not be equivalent."
144
- or
145
- flowstate = "NSString" and
146
- message = "This NSString length is used in a String, but it may not be equivalent."
147
- )
172
+ config .isSource ( source .getNode ( ) , sourceFlowState ) and
173
+ config .isSinkImpl ( sink .getNode ( ) , sinkFlowstate ) and
174
+ message =
175
+ "This " + sourceFlowState + " length is used in " + sinkFlowstate .getSingular ( ) +
176
+ ", but it may not be equivalent."
148
177
select sink .getNode ( ) , source , sink , message
0 commit comments