diff --git a/swift/ql/lib/codeql/swift/regex/Regex.qll b/swift/ql/lib/codeql/swift/regex/Regex.qll index 0ae533d6843..6b7e57e06c5 100644 --- a/swift/ql/lib/codeql/swift/regex/Regex.qll +++ b/swift/ql/lib/codeql/swift/regex/Regex.qll @@ -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())) ) }