Swift: Rework ParsedStringRegex and introduce the needed RegexPatternSource class.

This commit is contained in:
Geoffrey White
2023-08-16 15:47:03 +01:00
parent 6fb1058e73
commit 6deaf4e5f8

View File

@@ -8,6 +8,37 @@ private import codeql.swift.dataflow.DataFlow
private import internal.ParseRegex
private import internal.RegexTracking
/**
* A data flow node whose value may flow to a position where it is interpreted
* as a part of a regular expression. For example the string literal
* `"(a|b).*"` in:
* ```
* Regex("(a|b).*").firstMatch(in: myString)
* ```
*/
abstract class RegexPatternSource extends DataFlow::Node {
/**
* Gets a node where the pattern of this node is parsed as a part of
* a regular expression.
*/
abstract DataFlow::Node getAParse();
/**
* Gets the root term of the regular expression parsed from this pattern.
*/
abstract RegExpTerm getRegExpTerm();
}
/**
* For each `RegexPatternSource` data flow node, the corresponding `Expr` is
* a `Regex`. This is a simple wrapper to make that happen.
*/
private class RegexFromRegexPatternSource extends RegExp {
RegexPatternSource node;
RegexFromRegexPatternSource() { this = node.asExpr() }
}
/**
* A string literal that is used as a regular expression. For example
* the string literal `"(a|b).*"` in:
@@ -15,16 +46,18 @@ private import internal.RegexTracking
* Regex("(a|b).*").firstMatch(in: myString)
* ```
*/
private class ParsedStringRegex extends RegExp, StringLiteralExpr {
private class ParsedStringRegex extends RegexPatternSource {
StringLiteralExpr expr;
DataFlow::Node use;
ParsedStringRegex() { StringLiteralUseFlow::flow(DataFlow::exprNode(this), use) }
ParsedStringRegex() {
expr = this.asExpr() and
StringLiteralUseFlow::flow(this, use)
}
/**
* Gets a dataflow node where this string literal is used as a regular
* expression.
*/
DataFlow::Node getUse() { result = use }
override DataFlow::Node getAParse() { result = use }
override RegExpTerm getRegExpTerm() { result.getRegExp() = this.asExpr() }
}
/**
@@ -246,11 +279,11 @@ abstract class RegexEval extends CallExpr {
*/
RegExp getARegex() {
// string literal used directly as a regex
result.(ParsedStringRegex).getUse().asExpr() = this.getRegexInput()
DataFlow::exprNode(result).(ParsedStringRegex).getAParse().asExpr() = this.getRegexInput()
or
// string literal -> regex object -> use
exists(RegexCreation regexCreation |
result.(ParsedStringRegex).getUse() = regexCreation.getStringInput() and
DataFlow::exprNode(result).(ParsedStringRegex).getAParse() = regexCreation.getStringInput() and
RegexUseFlow::flow(regexCreation, DataFlow::exprNode(this.getRegexInput()))
)
}