Skip to content
445 changes: 445 additions & 0 deletions python/ql/src/semmle/python/Parser.qll

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions python/ql/src/semmle/python/PrintAst.qll
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import python
import semmle.python.RegexTreeView

private newtype TPrintAstConfiguration = MkPrintAstConfiguration()

Expand Down Expand Up @@ -53,6 +54,9 @@ private newtype TPrintAstNode =
not list = any(Module mod).getBody() and
not forall(AstNode child | child = list.getAnItem() | isNotNeeded(child)) and
exists(list.getAnItem())
} or
TRegExpTermNode(RegExpTerm term) {
exists(StrConst str | term.getRootTerm() = getParsedRegExp(str) and shouldPrint(str, _))
}

/**
Expand Down Expand Up @@ -419,6 +423,41 @@ class ParameterNode extends AstElementNode {
}
}

/**
* A print node for a `StrConst`.
*
* The string has a child, if the child is used as a regular expression,
* which is the root of the regular expression.
*/
class StrConstNode extends AstElementNode {
override StrConst element;

override PrintAstNode getChild(int childIndex) {
childIndex = 0 and result.(RegExpTermNode).getTerm() = getParsedRegExp(element)
}
}

/**
* A print node for a regular expression term.
*/
class RegExpTermNode extends TRegExpTermNode, PrintAstNode {
RegExpTerm term;

RegExpTermNode() { this = TRegExpTermNode(term) }

RegExpTerm getTerm() { result = term }

override PrintAstNode getChild(int childIndex) {
result.(RegExpTermNode).getTerm() = term.getChild(childIndex)
}

override string toString() {
result = "[" + strictconcat(term.getPrimaryQLClass(), " | ") + "] " + term.toString()
}

override Location getLocation() { result = term.getLocation() }
}

/**
* Gets the `i`th child from `node` ordered by location.
*/
Expand Down
30 changes: 30 additions & 0 deletions python/ql/src/semmle/python/RegexLiteral.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import python
import semmle.python.regex as R
private import RegexParserExtended

class RegexLiteralValue extends ParsedString {
R::Regex lit;

RegexLiteralValue() {
this = lit.getText() and
exists(lit.getLocation().getFile().getRelativePath())
}

override ParserConfiguration getConfiguration() { result instanceof RegexParserConfiguration }

override predicate getLocationInfo(
string file, int startline, int startcol, int endline, int endcol
) {
lit.getLocation().hasLocationInfo(file, startline + 1, startcol - 2, endline + 1, endcol - 2)
}

R::Regex getLiteral() { result = lit }
}

class RegexLiteral extends R::Regex {
RegexLiteralValue val;

RegexLiteral() { val.getLiteral() = this }

Regex getRegex() { result.getText() = val and result.isRoot() }
}
Loading