Skip to content

Commit 89d5bbb

Browse files
committed
Swift: Generalize the flow states in this query.
1 parent 9e77330 commit 89d5bbb

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

swift/ql/src/queries/Security/CWE-135/StringLengthConflation.ql

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@ import swift
1414
import codeql.swift.dataflow.DataFlow
1515
import DataFlow::PathGraph
1616

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+
1735
/**
1836
* A configuration for tracking string lengths originating from source that is
1937
* a `String` or an `NSString` object, to a sink of a different kind that
@@ -40,7 +58,11 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
4058
)
4159
}
4260

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) {
4466
// arguments to method calls...
4567
exists(
4668
string className, string methodName, string paramName, ClassDecl c, AbstractFunctionDecl f,
@@ -78,7 +100,7 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
78100
f.getName() = methodName and
79101
f.getParam(pragma[only_bind_into](arg)).getName() = paramName and
80102
call.getArgument(pragma[only_bind_into](arg)).getExpr() = node.asExpr() and
81-
flowstate = "String" // `String` length flowing into `NSString`
103+
flowstate = "NSString"
82104
)
83105
or
84106
// arguments to function calls...
@@ -89,7 +111,7 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
89111
call.getStaticTarget().getName() = funcName and
90112
call.getStaticTarget().getParam(pragma[only_bind_into](arg)).getName() = paramName and
91113
call.getArgument(pragma[only_bind_into](arg)).getExpr() = node.asExpr() and
92-
flowstate = "String" // `String` length flowing into `NSString`
114+
flowstate = "NSString"
93115
)
94116
or
95117
// arguments to function calls...
@@ -122,7 +144,16 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
122144
.getParam(pragma[only_bind_into](arg))
123145
.getName() = paramName and
124146
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
126157
)
127158
}
128159

@@ -134,15 +165,13 @@ class StringLengthConflationConfiguration extends DataFlow::Configuration {
134165

135166
from
136167
StringLengthConflationConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
137-
string flowstate, string message
168+
StringLengthConflationFlowState sourceFlowState, StringLengthConflationFlowState sinkFlowstate,
169+
string message
138170
where
139171
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."
148177
select sink.getNode(), source, sink, message

0 commit comments

Comments
 (0)