Skip to content

Commit 6deaf4e

Browse files
committed
Swift: Rework ParsedStringRegex and introduce the needed RegexPatternSource class.
1 parent 6fb1058 commit 6deaf4e

File tree

1 file changed

+42
-9
lines changed

1 file changed

+42
-9
lines changed

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

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,56 @@ private import codeql.swift.dataflow.DataFlow
88
private import internal.ParseRegex
99
private import internal.RegexTracking
1010

11+
/**
12+
* A data flow node whose value may flow to a position where it is interpreted
13+
* as a part of a regular expression. For example the string literal
14+
* `"(a|b).*"` in:
15+
* ```
16+
* Regex("(a|b).*").firstMatch(in: myString)
17+
* ```
18+
*/
19+
abstract class RegexPatternSource extends DataFlow::Node {
20+
/**
21+
* Gets a node where the pattern of this node is parsed as a part of
22+
* a regular expression.
23+
*/
24+
abstract DataFlow::Node getAParse();
25+
26+
/**
27+
* Gets the root term of the regular expression parsed from this pattern.
28+
*/
29+
abstract RegExpTerm getRegExpTerm();
30+
}
31+
32+
/**
33+
* For each `RegexPatternSource` data flow node, the corresponding `Expr` is
34+
* a `Regex`. This is a simple wrapper to make that happen.
35+
*/
36+
private class RegexFromRegexPatternSource extends RegExp {
37+
RegexPatternSource node;
38+
39+
RegexFromRegexPatternSource() { this = node.asExpr() }
40+
}
41+
1142
/**
1243
* A string literal that is used as a regular expression. For example
1344
* the string literal `"(a|b).*"` in:
1445
* ```
1546
* Regex("(a|b).*").firstMatch(in: myString)
1647
* ```
1748
*/
18-
private class ParsedStringRegex extends RegExp, StringLiteralExpr {
49+
private class ParsedStringRegex extends RegexPatternSource {
50+
StringLiteralExpr expr;
1951
DataFlow::Node use;
2052

21-
ParsedStringRegex() { StringLiteralUseFlow::flow(DataFlow::exprNode(this), use) }
53+
ParsedStringRegex() {
54+
expr = this.asExpr() and
55+
StringLiteralUseFlow::flow(this, use)
56+
}
2257

23-
/**
24-
* Gets a dataflow node where this string literal is used as a regular
25-
* expression.
26-
*/
27-
DataFlow::Node getUse() { result = use }
58+
override DataFlow::Node getAParse() { result = use }
59+
60+
override RegExpTerm getRegExpTerm() { result.getRegExp() = this.asExpr() }
2861
}
2962

3063
/**
@@ -246,11 +279,11 @@ abstract class RegexEval extends CallExpr {
246279
*/
247280
RegExp getARegex() {
248281
// string literal used directly as a regex
249-
result.(ParsedStringRegex).getUse().asExpr() = this.getRegexInput()
282+
DataFlow::exprNode(result).(ParsedStringRegex).getAParse().asExpr() = this.getRegexInput()
250283
or
251284
// string literal -> regex object -> use
252285
exists(RegexCreation regexCreation |
253-
result.(ParsedStringRegex).getUse() = regexCreation.getStringInput() and
286+
DataFlow::exprNode(result).(ParsedStringRegex).getAParse() = regexCreation.getStringInput() and
254287
RegexUseFlow::flow(regexCreation, DataFlow::exprNode(this.getRegexInput()))
255288
)
256289
}

0 commit comments

Comments
 (0)