JS: Introduce RegExpCreationNode

This commit is contained in:
Asger F
2019-11-20 14:41:33 +00:00
parent 4354945c26
commit ad6e949bad

View File

@@ -1315,3 +1315,131 @@ module PartialInvokeNode {
* This contributes additional argument-passing flow edges that should be added to all data flow configurations.
*/
deprecated class AdditionalPartialInvokeNode = PartialInvokeNode::Range;
/**
* An invocation of the `RegExp` constructor.
*
* Example:
* ```js
* new RegExp("#[a-z]+", "g");
* RegExp("^\w*$");
* ```
*/
class RegExpConstructorInvokeNode extends DataFlow::InvokeNode {
RegExpConstructorInvokeNode() {
this = DataFlow::globalVarRef("RegExp").getAnInvocation()
}
/**
* Gets the AST of the regular expression created here, if it is constant.
*/
RegExpTerm getRegExpTerm() {
result = getArgument(0).asExpr().(StringLiteral).asRegExp()
}
/**
* Gets the flags provided in the second argument, or an empty string if no
* flags are provided.
*
* Has no result if the flags are provided but are not constant.
*/
string getFlags() {
result = getArgument(1).getStringValue()
or
not exists(getArgument(1)) and
result = ""
}
/**
* Gets the flags provided in the second argument, or an empty string if no
* flags are provided, or the string `"?"` if the provided flags are not known.
*/
string tryGetFlags() {
result = getFlags()
or
not exists(getFlags()) and
result = RegExp::unknownFlag()
}
}
/**
* A data flow node corresponding to a regular expression literal.
*
* Example:
* ```js
* /[a-z]+/i
* ```
*/
class RegExpLiteralNode extends DataFlow::SourceNode, DataFlow::ValueNode {
override RegExpLiteral astNode;
/** Gets the root term of this regular expression literal. */
RegExpTerm getRegExpTerm() {
result = astNode.getRoot()
}
/** Gets the flags of this regular expression literal. */
string getFlags() {
result = astNode.getFlags()
}
}
/**
* A data flow node corresponding to a regular expression literal or
* an invocation of the `RegExp` constructor.
*
* Examples:
* ```js
* new RegExp("#[a-z]+", "g");
* RegExp("^\w*$");
* /[a-z]+/i
* ```
*/
class RegExpCreationNode extends DataFlow::SourceNode {
RegExpCreationNode() {
this instanceof RegExpConstructorInvokeNode or
this instanceof RegExpLiteralNode
}
/**
* Gets the root term of the created regular expression, if it is known.
*
* Has no result for calls to `RegExp` with a non-constant argument.
*/
RegExpTerm getRegExpTerm() {
result = this.(RegExpConstructorInvokeNode).getRegExpTerm() or
result = this.(RegExpLiteralNode).getRegExpTerm()
}
/**
* Gets the provided regular expression flags, if they are known.
*/
string getFlags() {
result = this.(RegExpConstructorInvokeNode).getFlags() or
result = this.(RegExpLiteralNode).getFlags()
}
/**
* Gets the flags provided in the second argument, or an empty string if no
* flags are provided, or the string `"?"` if the provided flags are not known.
*/
string tryGetFlags() {
result = this.(RegExpConstructorInvokeNode).tryGetFlags() or
result = this.(RegExpLiteralNode).getFlags()
}
/** Gets a data flow node referring to this regular expression. */
private DataFlow::SourceNode getAReference(DataFlow::TypeTracker t) {
t.start() and
result = this
or
exists(DataFlow::TypeTracker t2 |
result = getAReference(t2).track(t2, t)
)
}
/** Gets a data flow node referring to this regular expression. */
DataFlow::SourceNode getAReference() {
result = getAReference(DataFlow::TypeTracker::end())
}
}