Skip to content

Commit cdc0d1f

Browse files
committed
Swift: Check the options flag contains .regularExpression.
1 parent fe4ef48 commit cdc0d1f

File tree

3 files changed

+19
-62
lines changed

3 files changed

+19
-62
lines changed

swift/ql/lib/codeql/swift/regex/Regex.qll

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,15 @@ private class SometimesRegexEval extends RegexEval {
391391
) and
392392
regexInput.asExpr() = this.getArgument(0).getExpr() and
393393
stringInput.asExpr() = this.getQualifier() and
394-
optionsInput.asExpr() = this.getArgumentWithLabel("options").getExpr()
395-
// TODO: check options may have value `.regularExpression`
394+
optionsInput.asExpr() = this.getArgumentWithLabel("options").getExpr() and
395+
// flow from `.regularExpression` to `options` argument
396+
exists(MemberRefExpr sourceValue |
397+
sourceValue
398+
.getMember()
399+
.(FieldDecl)
400+
.hasQualifiedName("NSString.CompareOptions", "regularExpression") and
401+
DataFlow::localFlow(DataFlow::exprNode(sourceValue), optionsInput)
402+
)
396403
}
397404

398405
override DataFlow::Node getRegexInput() { result = regexInput }

swift/ql/test/library-tests/regex/parse.expected

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6334,21 +6334,11 @@ regex.swift:
63346334
# 129| [RegExpStar] .*
63356335
#-----| 0 -> [RegExpDot] .
63366336

6337-
# 130| [RegExpDot] .
6338-
6339-
# 130| [RegExpStar] .*
6340-
#-----| 0 -> [RegExpDot] .
6341-
63426337
# 131| [RegExpDot] .
63436338

63446339
# 131| [RegExpStar] .*
63456340
#-----| 0 -> [RegExpDot] .
63466341

6347-
# 132| [RegExpDot] .
6348-
6349-
# 132| [RegExpStar] .*
6350-
#-----| 0 -> [RegExpDot] .
6351-
63526342
# 136| [RegExpDot] .
63536343

63546344
# 136| [RegExpStar] .*
@@ -6359,36 +6349,16 @@ regex.swift:
63596349
# 150| [RegExpStar] .*
63606350
#-----| 0 -> [RegExpDot] .
63616351

6362-
# 151| [RegExpDot] .
6363-
6364-
# 151| [RegExpStar] .*
6365-
#-----| 0 -> [RegExpDot] .
6366-
63676352
# 152| [RegExpDot] .
63686353

63696354
# 152| [RegExpStar] .*
63706355
#-----| 0 -> [RegExpDot] .
63716356

6372-
# 153| [RegExpDot] .
6373-
6374-
# 153| [RegExpStar] .*
6375-
#-----| 0 -> [RegExpDot] .
6376-
6377-
# 154| [RegExpDot] .
6378-
6379-
# 154| [RegExpStar] .*
6380-
#-----| 0 -> [RegExpDot] .
6381-
63826357
# 155| [RegExpDot] .
63836358

63846359
# 155| [RegExpStar] .*
63856360
#-----| 0 -> [RegExpDot] .
63866361

6387-
# 156| [RegExpDot] .
6388-
6389-
# 156| [RegExpStar] .*
6390-
#-----| 0 -> [RegExpDot] .
6391-
63926362
# 160| [RegExpDot] .
63936363

63946364
# 160| [RegExpStar] .*
@@ -6643,23 +6613,3 @@ regex.swift:
66436613

66446614
# 246| [RegExpStar] .*
66456615
#-----| 0 -> [RegExpDot] .
6646-
6647-
# 251| [RegExpDot] .
6648-
6649-
# 251| [RegExpStar] .*
6650-
#-----| 0 -> [RegExpDot] .
6651-
6652-
# 252| [RegExpDot] .
6653-
6654-
# 252| [RegExpStar] .*
6655-
#-----| 0 -> [RegExpDot] .
6656-
6657-
# 253| [RegExpDot] .
6658-
6659-
# 253| [RegExpStar] .*
6660-
#-----| 0 -> [RegExpDot] .
6661-
6662-
# 254| [RegExpDot] .
6663-
6664-
# 254| [RegExpStar] .*
6665-
#-----| 0 -> [RegExpDot] .

swift/ql/test/library-tests/regex/regex.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,9 @@ func myRegexpMethodsTests(b: Bool, str_unknown: String) throws {
127127
// --- StringProtocol ---
128128

129129
_ = input.range(of: ".*", options: .regularExpression, range: nil, locale: nil) // $ regex=.* input=input
130-
_ = input.range(of: ".*", options: .literal, range: nil, locale: nil) // $ SPURIOUS: regex=.* input=input
130+
_ = input.range(of: ".*", options: .literal, range: nil, locale: nil) // (not a regular expression)
131131
_ = input.replacingOccurrences(of: ".*", with: "", options: .regularExpression) // $ regex=.* input=input
132-
_ = input.replacingOccurrences(of: ".*", with: "", options: .literal) // $ SPURIOUS: regex=.* input=input
132+
_ = input.replacingOccurrences(of: ".*", with: "", options: .literal) // (not a regular expression)
133133

134134
// --- NSRegularExpression ---
135135

@@ -148,12 +148,12 @@ func myRegexpMethodsTests(b: Bool, str_unknown: String) throws {
148148
let regexOptions = NSString.CompareOptions.regularExpression
149149
let regexOptions2 : NSString.CompareOptions = [.regularExpression, .caseInsensitive]
150150
_ = inputNS.range(of: ".*", options: .regularExpression) // $ regex=.* input=inputNS
151-
_ = inputNS.range(of: ".*", options: [.regularExpression]) // $ regex=.* input=inputNS
151+
_ = inputNS.range(of: ".*", options: [.regularExpression]) // $ MISSING: regex=.* input=inputNS
152152
_ = inputNS.range(of: ".*", options: regexOptions) // $ regex=.* input=inputNS
153-
_ = inputNS.range(of: ".*", options: regexOptions2) // $ regex=.* input=inputNS
154-
_ = inputNS.range(of: ".*", options: .literal) // $ SPURIOUS: regex=.* input=inputNS
153+
_ = inputNS.range(of: ".*", options: regexOptions2) // $ MISSING: regex=.* input=inputNS
154+
_ = inputNS.range(of: ".*", options: .literal) // (not a regular expression)
155155
_ = inputNS.replacingOccurrences(of: ".*", with: "", options: .regularExpression, range: NSMakeRange(0, inputNS.length)) // $ regex=.* input=inputNS
156-
_ = inputNS.replacingOccurrences(of: ".*", with: "", options: .literal, range: NSMakeRange(0, inputNS.length)) // $ SPURIOUS: regex=.* input=inputNS
156+
_ = inputNS.replacingOccurrences(of: ".*", with: "", options: .literal, range: NSMakeRange(0, inputNS.length)) // (not a regular expression)
157157

158158
// --- flow ---
159159

@@ -248,8 +248,8 @@ func myRegexpMethodsTests(b: Bool, str_unknown: String) throws {
248248
// parse modes set through other methods
249249

250250
let myOptions2 : NSString.CompareOptions = [.regularExpression, .caseInsensitive]
251-
_ = input.replacingOccurrences(of: ".*", with: "", options: [.regularExpression, .caseInsensitive]) // $ regex=.* input=input MISSING: modes=IGNORECASE
252-
_ = input.replacingOccurrences(of: ".*", with: "", options: myOptions2) // $ regex=.* input=input MISSING: modes=IGNORECASE
253-
_ = NSString(string: "abc").replacingOccurrences(of: ".*", with: "", options: [.regularExpression, .caseInsensitive], range: NSMakeRange(0, inputNS.length)) // $ regex=.* input="call to NSString.init(string:)" MISSING: modes=IGNORECASE
254-
_ = NSString(string: "abc").replacingOccurrences(of: ".*", with: "", options: myOptions2, range: NSMakeRange(0, inputNS.length)) // $ regex=.* input="call to NSString.init(string:)" MISSING: modes=IGNORECASE
251+
_ = input.replacingOccurrences(of: ".*", with: "", options: [.regularExpression, .caseInsensitive]) // $ MISSING: regex=.* input=input modes=IGNORECASE
252+
_ = input.replacingOccurrences(of: ".*", with: "", options: myOptions2) // $ MISSING: regex=.* input=input modes=IGNORECASE
253+
_ = NSString(string: "abc").replacingOccurrences(of: ".*", with: "", options: [.regularExpression, .caseInsensitive], range: NSMakeRange(0, inputNS.length)) // $ MISSING: regex=.* input="call to NSString.init(string:)" modes=IGNORECASE
254+
_ = NSString(string: "abc").replacingOccurrences(of: ".*", with: "", options: myOptions2, range: NSMakeRange(0, inputNS.length)) // $ MISSING: regex=.* input="call to NSString.init(string:)" modes=IGNORECASE
255255
}

0 commit comments

Comments
 (0)