cache more predicates

This commit is contained in:
Erik Krogh Kristensen
2021-11-19 11:15:34 +01:00
parent 089d030bc2
commit f39872e649
5 changed files with 60 additions and 4 deletions

View File

@@ -3,10 +3,12 @@
*/
import javascript
private import semmle.javascript.internal.CachedStages
/**
* An expression that evaluates to a constant primitive value.
*/
cached
abstract class ConstantExpr extends Expr { }
/**
@@ -16,6 +18,7 @@ module SyntacticConstants {
/**
* An expression that evaluates to a constant value according to a bottom-up syntactic analysis.
*/
cached
abstract class SyntacticConstant extends ConstantExpr { }
/**
@@ -23,8 +26,11 @@ module SyntacticConstants {
*
* Note that `undefined`, `NaN` and `Infinity` are global variables, and are not covered by this class.
*/
cached
class PrimitiveLiteralConstant extends SyntacticConstant {
cached
PrimitiveLiteralConstant() {
Stages::Ast::ref() and
this instanceof NumberLiteral
or
this instanceof StringLiteral
@@ -43,19 +49,27 @@ module SyntacticConstants {
/**
* A literal null expression.
*/
class NullConstant extends SyntacticConstant, NullLiteral { }
cached
class NullConstant extends SyntacticConstant, NullLiteral {
cached
NullConstant() { Stages::Ast::ref() and this = this }
}
/**
* A unary operation on a syntactic constant.
*/
cached
class UnaryConstant extends SyntacticConstant, UnaryExpr {
cached
UnaryConstant() { getOperand() instanceof SyntacticConstant }
}
/**
* A binary operation on syntactic constants.
*/
cached
class BinaryConstant extends SyntacticConstant, BinaryExpr {
cached
BinaryConstant() {
getLeftOperand() instanceof SyntacticConstant and
getRightOperand() instanceof SyntacticConstant
@@ -65,7 +79,9 @@ module SyntacticConstants {
/**
* A conditional expression on syntactic constants.
*/
cached
class ConditionalConstant extends SyntacticConstant, ConditionalExpr {
cached
ConditionalConstant() {
getCondition() instanceof SyntacticConstant and
getConsequent() instanceof SyntacticConstant and
@@ -76,7 +92,9 @@ module SyntacticConstants {
/**
* A use of the global variable `undefined` or `void e`.
*/
cached
class UndefinedConstant extends SyntacticConstant {
cached
UndefinedConstant() {
this.(GlobalVarAccess).getName() = "undefined" or
this instanceof VoidExpr
@@ -86,21 +104,27 @@ module SyntacticConstants {
/**
* A use of the global variable `NaN`.
*/
cached
class NaNConstant extends SyntacticConstant {
cached
NaNConstant() { this.(GlobalVarAccess).getName() = "NaN" }
}
/**
* A use of the global variable `Infinity`.
*/
cached
class InfinityConstant extends SyntacticConstant {
cached
InfinityConstant() { this.(GlobalVarAccess).getName() = "Infinity" }
}
/**
* An expression that wraps the syntactic constant it evaluates to.
*/
cached
class WrappedConstant extends SyntacticConstant {
cached
WrappedConstant() { getUnderlyingValue() instanceof SyntacticConstant }
}
@@ -123,6 +147,8 @@ module SyntacticConstants {
/**
* An expression that evaluates to a constant string.
*/
cached
class ConstantString extends ConstantExpr {
cached
ConstantString() { exists(getStringValue()) }
}

View File

@@ -89,7 +89,8 @@ class ExprOrType extends @expr_or_type, Documentable {
*
* Also see `getUnderlyingReference` and `stripParens`.
*/
Expr getUnderlyingValue() { result = this }
cached
Expr getUnderlyingValue() { Stages::Ast::ref() and result = this }
}
/**
@@ -274,7 +275,11 @@ private DataFlow::Node getCatchParameterFromStmt(Stmt stmt) {
*/
class Identifier extends @identifier, ExprOrType {
/** Gets the name of this identifier. */
string getName() { literals(result, _, this) }
cached
string getName() {
Stages::Ast::ref() and
literals(result, _, this)
}
override string getAPrimaryQlClass() { result = "Identifier" }
}

View File

@@ -165,6 +165,7 @@ module MembershipCandidate {
EnumerationRegExp enumeration;
boolean polarity;
pragma[nomagic]
RegExpEnumerationCandidate() {
exists(DataFlow::MethodCallNode mcn, DataFlow::Node base, string m, DataFlow::Node firstArg |
(

View File

@@ -160,10 +160,12 @@ module TaintTracking {
* of the standard library. Override `Configuration::isSanitizerGuard`
* for analysis-specific taint sanitizer guards.
*/
cached
abstract class AdditionalSanitizerGuardNode extends SanitizerGuardNode {
/**
* Holds if this guard applies to the flow in `cfg`.
*/
cached
abstract predicate appliesTo(Configuration cfg);
}
@@ -1127,7 +1129,7 @@ module TaintTracking {
idx = astNode.getAnOperand() and
idx.getPropertyNameExpr() = x and
// and the other one is guaranteed to be `undefined`
forex(InferredType tp | tp = undef.getAType() | tp = TTUndefined())
unique(InferredType tp | tp = pragma[only_bind_into](undef.getAType())) = TTUndefined()
)
}

View File

@@ -69,6 +69,14 @@ module Stages {
exists(any(Expr e).getStringValue())
or
any(ASTNode node).isAmbient()
or
exists(any(Identifier e).getName())
or
exists(any(ExprOrType e).getUnderlyingValue())
or
exists(ConstantExpr e)
or
exists(SyntacticConstants::NullConstant n)
}
}
@@ -299,6 +307,20 @@ module Stages {
exists(Exports::getALibraryInputParameter())
or
any(RegExpTerm t).isUsedAsRegExp()
or
any(TaintTracking::AdditionalSanitizerGuardNode e).appliesTo(_)
}
cached
class DummySanitizer extends TaintTracking::AdditionalSanitizerGuardNode {
cached
DummySanitizer() { none() }
cached
override predicate appliesTo(TaintTracking::Configuration cfg) { none() }
cached
override predicate sanitizes(boolean outcome, Expr e) { none() }
}
}
}