mirror of
https://github.com/github/codeql.git
synced 2026-04-27 09:45:15 +02:00
JavaScript: Autoformat.
This commit is contained in:
@@ -17,7 +17,6 @@ import DataFlow::PathGraph
|
||||
*/
|
||||
class DecodingCall extends CallNode {
|
||||
string kind;
|
||||
|
||||
Node input;
|
||||
|
||||
DecodingCall() {
|
||||
|
||||
@@ -12,7 +12,6 @@ import javascript
|
||||
*/
|
||||
class SuppressionComment extends Locatable {
|
||||
string text;
|
||||
|
||||
string annotation;
|
||||
|
||||
SuppressionComment() {
|
||||
|
||||
@@ -32,7 +32,6 @@ predicate isResourceUrlWhitelist(
|
||||
*/
|
||||
class ResourceUrlWhitelistEntry extends Expr {
|
||||
DataFlow::MethodCallNode setupCall;
|
||||
|
||||
string pattern;
|
||||
|
||||
ResourceUrlWhitelistEntry() {
|
||||
|
||||
@@ -58,9 +58,8 @@ where
|
||||
(
|
||||
// To avoid confusion about the meaning of "definition" and "declaration" we avoid
|
||||
// the term "definition" when the alert location is a variable declaration.
|
||||
if dead instanceof VariableDeclarator then
|
||||
msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten."
|
||||
else
|
||||
msg = "This definition of " + v.getName() + " is useless, since its value is never read."
|
||||
if dead instanceof VariableDeclarator
|
||||
then msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten."
|
||||
else msg = "This definition of " + v.getName() + " is useless, since its value is never read."
|
||||
)
|
||||
select dead, msg
|
||||
|
||||
@@ -160,7 +160,8 @@ where
|
||||
) and
|
||||
// exclude results from non-value definitions from `Object.defineProperty`
|
||||
(
|
||||
assign1 instanceof CallToObjectDefineProperty implies
|
||||
assign1 instanceof CallToObjectDefineProperty
|
||||
implies
|
||||
assign1.(CallToObjectDefineProperty).hasPropertyAttributeWrite("value", _)
|
||||
)
|
||||
select assign1.getWriteNode(),
|
||||
|
||||
@@ -34,15 +34,16 @@ predicate hasUnknownPropertyRead(LocalObject obj) {
|
||||
* Holds if `obj` flows to an expression that must have a specific type.
|
||||
*/
|
||||
predicate flowsToTypeRestrictedExpression(LocalObject obj) {
|
||||
exists (Expr restricted, TypeExpr type |
|
||||
exists(Expr restricted, TypeExpr type |
|
||||
obj.flowsToExpr(restricted) and
|
||||
not type.isAny() |
|
||||
exists (TypeAssertion assertion |
|
||||
not type.isAny()
|
||||
|
|
||||
exists(TypeAssertion assertion |
|
||||
type = assertion.getTypeAnnotation() and
|
||||
restricted = assertion.getExpression()
|
||||
)
|
||||
or
|
||||
exists (BindingPattern v |
|
||||
exists(BindingPattern v |
|
||||
type = v.getTypeAnnotation() and
|
||||
restricted = v.getAVariable().getAnAssignedExpr()
|
||||
)
|
||||
|
||||
@@ -36,16 +36,16 @@ predicate isDeclaration(Expr e) {
|
||||
*/
|
||||
predicate isGetterProperty(string name) {
|
||||
// there is a call of the form `Object.defineProperty(..., name, descriptor)` ...
|
||||
exists(CallToObjectDefineProperty defProp |
|
||||
name = defProp.getPropertyName() |
|
||||
exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() |
|
||||
// ... where `descriptor` defines a getter
|
||||
defProp.hasPropertyAttributeWrite("get", _) or
|
||||
defProp.hasPropertyAttributeWrite("get", _)
|
||||
or
|
||||
// ... where `descriptor` may define a getter
|
||||
exists (DataFlow::SourceNode descriptor |
|
||||
descriptor.flowsTo(defProp.getPropertyDescriptor()) |
|
||||
descriptor.isIncomplete(_) or
|
||||
exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) |
|
||||
descriptor.isIncomplete(_)
|
||||
or
|
||||
// minimal escape analysis for the descriptor
|
||||
exists (DataFlow::InvokeNode invk |
|
||||
exists(DataFlow::InvokeNode invk |
|
||||
not invk = defProp and
|
||||
descriptor.flowsTo(invk.getAnArgument())
|
||||
)
|
||||
|
||||
@@ -28,9 +28,10 @@ private predicate isBoundInMethod(MethodDeclaration method) {
|
||||
)
|
||||
or
|
||||
// require("auto-bind")(this)
|
||||
exists (string mod |
|
||||
exists(string mod |
|
||||
mod = "auto-bind" or
|
||||
mod = "react-autobind" |
|
||||
mod = "react-autobind"
|
||||
|
|
||||
thiz.flowsTo(DataFlow::moduleImport(mod).getACall().getArgument(0))
|
||||
)
|
||||
or
|
||||
|
||||
@@ -18,7 +18,6 @@ class CandidateTopLevel extends TopLevel {
|
||||
/** A string literal in a toplevel that contains at least one template literal. */
|
||||
class CandidateStringLiteral extends StringLiteral {
|
||||
CandidateTopLevel tl;
|
||||
|
||||
string v;
|
||||
|
||||
CandidateStringLiteral() {
|
||||
|
||||
@@ -395,7 +395,6 @@ newtype TStatePair =
|
||||
|
||||
class StatePair extends TStatePair {
|
||||
State q1;
|
||||
|
||||
State q2;
|
||||
|
||||
StatePair() { this = MkStatePair(q1, q2) }
|
||||
|
||||
@@ -109,7 +109,6 @@ predicate isDerivedFromLength(DataFlow::Node length, DataFlow::Node operand) {
|
||||
*/
|
||||
class UnsafeIndexOfComparison extends EqualityTest {
|
||||
IndexOfCall indexOf;
|
||||
|
||||
DataFlow::Node testedValue;
|
||||
|
||||
UnsafeIndexOfComparison() {
|
||||
|
||||
@@ -37,7 +37,8 @@ predicate isInterestingSemiAnchoredRegExpString(RegExpPatternSource src, string
|
||||
) and
|
||||
anchorPart = src.getPattern().regexpCapture(regex, 1) and
|
||||
anchorPart.regexpMatch("(?i).*[a-z].*") and
|
||||
msg = "Misleading operator precedence. The subexpression '" + anchorPart + "' is anchored, but the other parts of this regular expression are not"
|
||||
msg = "Misleading operator precedence. The subexpression '" + anchorPart +
|
||||
"' is anchored, but the other parts of this regular expression are not"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class Replacement extends DataFlow::Node {
|
||||
Replacement() {
|
||||
exists(DataFlow::MethodCallNode mcn | this = mcn |
|
||||
mcn.getMethodName() = "replace" and
|
||||
pattern.flow().(DataFlow::SourceNode).flowsTo(mcn.getArgument(0))and
|
||||
pattern.flow().(DataFlow::SourceNode).flowsTo(mcn.getArgument(0)) and
|
||||
mcn.getNumArgument() = 2 and
|
||||
pattern.isGlobal()
|
||||
)
|
||||
|
||||
@@ -64,4 +64,4 @@ where
|
||||
pwd = val.regexpCapture("(?is).*password\\s*=\\s*(?!;|\"?[$`]|%s|=)(\\S+).*", 1)
|
||||
) and
|
||||
not exclude(valElement.getFile())
|
||||
select (FirstLineOf)valElement, "Hard-coded password '" + pwd + "' in configuration file."
|
||||
select valElement.(FirstLineOf), "Hard-coded password '" + pwd + "' in configuration file."
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name Prototype pollution
|
||||
* @description Recursively merging a user-controlled object into another object
|
||||
* can allow an attacker to modify the built-in Object prototype.
|
||||
* can allow an attacker to modify the built-in Object prototype.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
@@ -17,7 +17,8 @@ import DataFlow::PathGraph
|
||||
import semmle.javascript.dependencies.Dependencies
|
||||
|
||||
from
|
||||
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string moduleName, Locatable dependencyLoc
|
||||
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string moduleName,
|
||||
Locatable dependencyLoc
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
sink.getNode().(Sink).dependencyInfo(moduleName, dependencyLoc)
|
||||
|
||||
@@ -135,9 +135,7 @@ class AdditionalStepSpec extends ExternalData {
|
||||
|
||||
private class AdditionalFlowStepFromSpec extends DataFlow::Configuration {
|
||||
AdditionalStepSpec spec;
|
||||
|
||||
DataFlow::Node entry;
|
||||
|
||||
DataFlow::Node exit;
|
||||
|
||||
AdditionalFlowStepFromSpec() {
|
||||
|
||||
@@ -36,9 +36,7 @@ external predicate additionalSteps(
|
||||
*/
|
||||
private class AdditionalSourceFromSpec extends DataFlow::AdditionalSource {
|
||||
Portal portal;
|
||||
|
||||
string flowLabel;
|
||||
|
||||
string config;
|
||||
|
||||
AdditionalSourceFromSpec() {
|
||||
@@ -56,9 +54,7 @@ private class AdditionalSourceFromSpec extends DataFlow::AdditionalSource {
|
||||
*/
|
||||
private class AdditionalSinkFromSpec extends DataFlow::AdditionalSink {
|
||||
Portal portal;
|
||||
|
||||
string flowLabel;
|
||||
|
||||
string config;
|
||||
|
||||
AdditionalSinkFromSpec() {
|
||||
@@ -76,11 +72,8 @@ private class AdditionalSinkFromSpec extends DataFlow::AdditionalSink {
|
||||
*/
|
||||
private class AdditionalFlowStepFromSpec extends DataFlow::Configuration {
|
||||
DataFlow::Node entry;
|
||||
|
||||
string startFlowLabel;
|
||||
|
||||
DataFlow::Node exit;
|
||||
|
||||
string endFlowLabel;
|
||||
|
||||
AdditionalFlowStepFromSpec() {
|
||||
|
||||
@@ -10,9 +10,7 @@ class PortalEntrySink extends DataFlow::AdditionalSink {
|
||||
|
||||
PortalEntrySink() { this = p.getAnEntryNode(true) }
|
||||
|
||||
override predicate isSinkFor(DataFlow::Configuration cfg, DataFlow::FlowLabel lbl) {
|
||||
any()
|
||||
}
|
||||
override predicate isSinkFor(DataFlow::Configuration cfg, DataFlow::FlowLabel lbl) { any() }
|
||||
|
||||
/** Gets the portal of which this is an entry node. */
|
||||
Portal getPortal() { result = p }
|
||||
|
||||
@@ -10,9 +10,7 @@ class PortalExitSource extends DataFlow::AdditionalSource {
|
||||
|
||||
PortalExitSource() { this = p.getAnExitNode(true) }
|
||||
|
||||
override predicate isSourceFor(DataFlow::Configuration cfg, DataFlow::FlowLabel lbl) {
|
||||
any()
|
||||
}
|
||||
override predicate isSourceFor(DataFlow::Configuration cfg, DataFlow::FlowLabel lbl) { any() }
|
||||
|
||||
/** Gets the portal of which this is an exit node. */
|
||||
Portal getPortal() { result = p }
|
||||
|
||||
@@ -61,7 +61,6 @@ class SpliceCall extends ArrayShiftingCall {
|
||||
*/
|
||||
class ArrayIterationLoop extends ForStmt {
|
||||
DataFlow::SourceNode array;
|
||||
|
||||
LocalVariable indexVariable;
|
||||
|
||||
ArrayIterationLoop() {
|
||||
|
||||
@@ -26,7 +26,7 @@ where
|
||||
// ignore ambient statements
|
||||
not s.isAmbient() and
|
||||
// ignore empty statements
|
||||
not s instanceof EmptyStmt and
|
||||
not s instanceof EmptyStmt and
|
||||
// ignore unreachable throws
|
||||
not s instanceof ThrowStmt
|
||||
select s.(FirstLineOf), "This statement is unreachable."
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
|
||||
private import semmle.javascript.dependencies.Dependencies
|
||||
private import semmle.javascript.dependencies.FrameworkLibraries
|
||||
@@ -96,17 +95,13 @@ predicate isExternalLibrary(string name) {
|
||||
* Holds if the global variable `name` is defined externally.
|
||||
*/
|
||||
predicate isExternalGlobal(string name) {
|
||||
exists(ExternalGlobalDecl decl |
|
||||
decl.getName() = name
|
||||
)
|
||||
exists(ExternalGlobalDecl decl | decl.getName() = name)
|
||||
or
|
||||
exists(Dependency dep |
|
||||
// If name is never assigned anywhere, and it coincides with a dependency,
|
||||
// it's most likely coming from there.
|
||||
dep.info(name, _) and
|
||||
not exists(Assignment assign |
|
||||
assign.getLhs().(GlobalVarAccess).getName() = name
|
||||
)
|
||||
not exists(Assignment assign | assign.getLhs().(GlobalVarAccess).getName() = name)
|
||||
)
|
||||
or
|
||||
name = "_"
|
||||
@@ -229,9 +224,7 @@ class UnresolvableCall extends RelevantInvoke {
|
||||
* A call that is believed to call a function within the same project.
|
||||
*/
|
||||
class NonExternalCall extends RelevantInvoke {
|
||||
NonExternalCall() {
|
||||
not this instanceof ExternalCall
|
||||
}
|
||||
NonExternalCall() { not this instanceof ExternalCall }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +242,5 @@ class FunctionWithCallers extends RelevantFunction {
|
||||
* A function without any call sites.
|
||||
*/
|
||||
class FunctionWithoutCallers extends RelevantFunction {
|
||||
FunctionWithoutCallers() {
|
||||
not this instanceof FunctionWithCallers
|
||||
}
|
||||
FunctionWithoutCallers() { not this instanceof FunctionWithCallers }
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
/**
|
||||
* @name Called function candidates
|
||||
* @description The number of functions for which finding call sites is relevant
|
||||
* for analysis quality.
|
||||
* for analysis quality.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/called-function-candidates
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
* @tags meta
|
||||
* @id js/meta/called-function-ratio
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
select projectRoot(), 100.0 * count(FunctionWithCallers f) / (float) count(RelevantFunction f)
|
||||
select projectRoot(), 100.0 * count(FunctionWithCallers f) / count(RelevantFunction f).(float)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags meta
|
||||
* @id js/meta/called-functions
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags meta
|
||||
* @id js/meta/resolvable-call-candidates
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
* @tags meta
|
||||
* @id js/meta/resolvable-call-ratio
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
select projectRoot(), 100.0 * count(ResolvableCall call) / (float) count(NonExternalCall call)
|
||||
select projectRoot(), 100.0 * count(ResolvableCall call) / count(NonExternalCall call).(float)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags meta
|
||||
* @id js/meta/resolvable-calls
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags meta
|
||||
* @id js/meta/uncalled-functions
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags meta
|
||||
* @id js/meta/unresolvable-calls
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
|
||||
@@ -160,8 +160,8 @@ class TopLevel extends @toplevel, StmtContainer {
|
||||
)
|
||||
or
|
||||
// many variables, and they all have short names
|
||||
count (VarDecl d | d.getTopLevel() = this) > 100 and
|
||||
forall (VarDecl d | d.getTopLevel() = this | d.getName().length() <= 2)
|
||||
count(VarDecl d | d.getTopLevel() = this) > 100 and
|
||||
forall(VarDecl d | d.getTopLevel() = this | d.getName().length() <= 2)
|
||||
}
|
||||
|
||||
/** Holds if this toplevel is an externs definitions file. */
|
||||
|
||||
@@ -95,6 +95,7 @@ private module Internal {
|
||||
exists(BasicBlock predBB | succBB(predBB, bb) | reachableBB(predBB))
|
||||
}
|
||||
}
|
||||
|
||||
private import Internal
|
||||
|
||||
/** Holds if `dom` is an immediate dominator of `bb`. */
|
||||
|
||||
@@ -10,7 +10,7 @@ import javascript
|
||||
* <pre>
|
||||
* // a line comment
|
||||
* /* a block
|
||||
* comment */
|
||||
* comment */
|
||||
* <!-- an HTML line comment
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
@@ -288,7 +288,7 @@ module DOM {
|
||||
/**
|
||||
* A data flow node that should be considered a source of DOM values.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {}
|
||||
abstract class Range extends DataFlow::Node { }
|
||||
|
||||
private class DefaultRange extends Range {
|
||||
DefaultRange() {
|
||||
@@ -301,9 +301,7 @@ module DOM {
|
||||
}
|
||||
|
||||
/** Gets a data flow node that refers directly to a value from the DOM. */
|
||||
DataFlow::SourceNode domValueSource() {
|
||||
result instanceof DomValueSource::Range
|
||||
}
|
||||
DataFlow::SourceNode domValueSource() { result instanceof DomValueSource::Range }
|
||||
|
||||
/** Gets a data flow node that may refer to a value from the DOM. */
|
||||
private DataFlow::SourceNode domValueRef(DataFlow::TypeTracker t) {
|
||||
@@ -322,7 +320,7 @@ module DOM {
|
||||
*
|
||||
* Can be subclassed to add additional such nodes.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {}
|
||||
abstract class Range extends DataFlow::Node { }
|
||||
|
||||
private class DefaultRange extends Range {
|
||||
DefaultRange() {
|
||||
@@ -342,9 +340,7 @@ module DOM {
|
||||
}
|
||||
|
||||
/** Gets a data flow node that directly refers to a DOM `location` object. */
|
||||
DataFlow::SourceNode locationSource() {
|
||||
result instanceof LocationSource::Range
|
||||
}
|
||||
DataFlow::SourceNode locationSource() { result instanceof LocationSource::Range }
|
||||
|
||||
/** Gets a reference to a DOM `location` object. */
|
||||
private DataFlow::SourceNode locationRef(DataFlow::TypeTracker t) {
|
||||
@@ -363,7 +359,7 @@ module DOM {
|
||||
*
|
||||
* Can be subclassed to add additional such nodes.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {}
|
||||
abstract class Range extends DataFlow::Node { }
|
||||
|
||||
private class DefaultRange extends Range {
|
||||
DefaultRange() { this = DataFlow::globalVarRef("document") }
|
||||
@@ -373,9 +369,7 @@ module DOM {
|
||||
/**
|
||||
* Gets a direct reference to the `document` object.
|
||||
*/
|
||||
DataFlow::SourceNode documentSource() {
|
||||
result instanceof DocumentSource::Range
|
||||
}
|
||||
DataFlow::SourceNode documentSource() { result instanceof DocumentSource::Range }
|
||||
|
||||
/**
|
||||
* Gets a reference to the `document` object.
|
||||
|
||||
@@ -84,7 +84,6 @@ module Internal {
|
||||
*/
|
||||
private class CompositeUndefinedNullTestPart extends DefensiveExpressionTest {
|
||||
UndefinedNullTest test;
|
||||
|
||||
boolean polarity;
|
||||
|
||||
CompositeUndefinedNullTestPart() {
|
||||
@@ -114,7 +113,6 @@ module Internal {
|
||||
*/
|
||||
private class SanityCheckingUndefinedNullGuard extends DefensiveExpressionTest {
|
||||
UndefinedNullTest test;
|
||||
|
||||
boolean polarity;
|
||||
|
||||
SanityCheckingUndefinedNullGuard() {
|
||||
@@ -152,7 +150,6 @@ module Internal {
|
||||
*/
|
||||
private class NullUndefinedComparison extends UndefinedNullTest {
|
||||
Expr operand;
|
||||
|
||||
InferredType op2type;
|
||||
|
||||
NullUndefinedComparison() {
|
||||
@@ -268,7 +265,6 @@ module Internal {
|
||||
*/
|
||||
private class UndefinedNullTruthinessGuard extends DefensiveExpressionTest {
|
||||
VarRef guardVar;
|
||||
|
||||
boolean polarity;
|
||||
|
||||
UndefinedNullTruthinessGuard() {
|
||||
@@ -296,7 +292,6 @@ module Internal {
|
||||
*/
|
||||
private class UndefinedNullTypeGuard extends DefensiveExpressionTest {
|
||||
UndefinedNullTest test;
|
||||
|
||||
boolean polarity;
|
||||
|
||||
UndefinedNullTypeGuard() {
|
||||
@@ -324,7 +319,6 @@ module Internal {
|
||||
*/
|
||||
private class TypeofTest extends EqualityTest {
|
||||
Expr operand;
|
||||
|
||||
TypeofTag tag;
|
||||
|
||||
TypeofTest() {
|
||||
@@ -362,7 +356,6 @@ module Internal {
|
||||
*/
|
||||
private class FunctionTypeGuard extends DefensiveExpressionTest {
|
||||
TypeofTest test;
|
||||
|
||||
boolean polarity;
|
||||
|
||||
FunctionTypeGuard() {
|
||||
|
||||
@@ -14,8 +14,7 @@ module E4X {
|
||||
* *
|
||||
* ```
|
||||
*/
|
||||
class XMLAnyName extends Expr, @e4x_xml_anyname {
|
||||
}
|
||||
class XMLAnyName extends Expr, @e4x_xml_anyname { }
|
||||
|
||||
/**
|
||||
* An E4X qualified identifier.
|
||||
@@ -133,4 +132,4 @@ module E4X {
|
||||
result = getBase().getFirstControlFlowNode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +334,8 @@ class ExportDefaultDeclaration extends ExportDeclaration, @exportdefaultdeclarat
|
||||
}
|
||||
}
|
||||
|
||||
/** A named export declaration.
|
||||
/**
|
||||
* A named export declaration.
|
||||
* *
|
||||
* Examples:
|
||||
*
|
||||
@@ -343,7 +344,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @exportdefaultdeclarat
|
||||
* export var x = 42;
|
||||
* export { x } from 'a';
|
||||
* ```
|
||||
* */
|
||||
*/
|
||||
class ExportNamedDeclaration extends ExportDeclaration, @exportnameddeclaration {
|
||||
/** Gets the operand statement or expression that is exported by this declaration. */
|
||||
ExprOrStmt getOperand() { result = getChild(-1) }
|
||||
|
||||
@@ -36,33 +36,19 @@ class ExprOrType extends @exprortype, Documentable {
|
||||
// if there is no JSDoc for the expression itself, check the enclosing property or statement
|
||||
not exists(getOwnDocumentation()) and
|
||||
(
|
||||
exists(Property prop | prop = getParent() |
|
||||
result = prop.getDocumentation()
|
||||
)
|
||||
exists(Property prop | prop = getParent() | result = prop.getDocumentation())
|
||||
or
|
||||
exists(MethodDeclaration decl | decl = getParent() |
|
||||
result = decl.getDocumentation()
|
||||
)
|
||||
exists(MethodDeclaration decl | decl = getParent() | result = decl.getDocumentation())
|
||||
or
|
||||
exists(VariableDeclarator decl | decl = getParent() |
|
||||
result = decl.getDocumentation()
|
||||
)
|
||||
exists(VariableDeclarator decl | decl = getParent() | result = decl.getDocumentation())
|
||||
or
|
||||
exists(DeclStmt stmt | this = stmt.getDecl(0) |
|
||||
result = stmt.getDocumentation()
|
||||
)
|
||||
exists(DeclStmt stmt | this = stmt.getDecl(0) | result = stmt.getDocumentation())
|
||||
or
|
||||
exists(DotExpr dot | this = dot.getProperty() |
|
||||
result = dot.getDocumentation()
|
||||
)
|
||||
exists(DotExpr dot | this = dot.getProperty() | result = dot.getDocumentation())
|
||||
or
|
||||
exists(AssignExpr e | this = e.getRhs() |
|
||||
result = e.getDocumentation()
|
||||
)
|
||||
exists(AssignExpr e | this = e.getRhs() | result = e.getDocumentation())
|
||||
or
|
||||
exists(ParExpr p | this = p.getExpression() |
|
||||
result = p.getDocumentation()
|
||||
)
|
||||
exists(ParExpr p | this = p.getExpression() | result = p.getDocumentation())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -203,13 +189,13 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
|
||||
/**
|
||||
* Holds if the syntactic context that the expression appears in relies on the expression
|
||||
* being non-null/non-undefined.
|
||||
*
|
||||
*
|
||||
* A context relies on the subexpression being non-null/non-undefined if either...
|
||||
*
|
||||
*
|
||||
* * Using null or undefined would cause a runtime error
|
||||
* * Using null or undefined would cause no error due to type conversion, but the
|
||||
* behavior in the broader context is sufficiently non-obvious to warrant explicitly
|
||||
* converting to ensure that readers understand the intent
|
||||
* converting to ensure that readers understand the intent
|
||||
*/
|
||||
predicate inNullSensitiveContext() {
|
||||
exists(ExprOrStmt ctx |
|
||||
@@ -668,7 +654,7 @@ class Property extends @property, Documentable {
|
||||
|
||||
/**
|
||||
* A value property definition in an object literal.
|
||||
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
@@ -2377,7 +2363,6 @@ class LegacyLetExpr extends Expr, @legacy_letexpr {
|
||||
class ImmediatelyInvokedFunctionExpr extends Function {
|
||||
/** The invocation expression of this IIFE. */
|
||||
InvokeExpr invk;
|
||||
|
||||
/**
|
||||
* The kind of invocation by which this IIFE is invoked: `"call"`
|
||||
* for a direct function call, `"call"` or `"apply"` for a reflective
|
||||
|
||||
@@ -74,9 +74,7 @@ abstract class Container extends @container {
|
||||
* <tr><td>"//FileServer/"</td><td>""</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getBaseName() {
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 1)
|
||||
}
|
||||
string getBaseName() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 1) }
|
||||
|
||||
/**
|
||||
* Gets the extension of this container, that is, the suffix of its base name
|
||||
@@ -101,7 +99,9 @@ abstract class Container extends @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getExtension() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 4) }
|
||||
string getExtension() {
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 4)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stem of this container, that is, the prefix of its base name up to
|
||||
|
||||
@@ -157,9 +157,7 @@ private int countStartingHtmlElements(File f, int l) {
|
||||
/**
|
||||
* Holds if the base name of `f` is a number followed by a single extension.
|
||||
*/
|
||||
predicate isGeneratedFileName(File f) {
|
||||
f.getStem().regexpMatch("[0-9]+")
|
||||
}
|
||||
predicate isGeneratedFileName(File f) { f.getStem().regexpMatch("[0-9]+") }
|
||||
|
||||
/**
|
||||
* Holds if `tl` looks like it contains generated code.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Provides predicates for associating qualified names with data flow nodes.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
module GlobalAccessPath {
|
||||
@@ -13,14 +14,10 @@ module GlobalAccessPath {
|
||||
}
|
||||
|
||||
/** Gets the SSA definition of this variable. */
|
||||
SsaExplicitDefinition getSsaDefinition() {
|
||||
result.getSourceVariable() = this
|
||||
}
|
||||
SsaExplicitDefinition getSsaDefinition() { result.getSourceVariable() = this }
|
||||
|
||||
/** Gets the data flow node representing the value of this variable, if one exists. */
|
||||
DataFlow::Node getValue() {
|
||||
result = getSsaDefinition().getRhsNode()
|
||||
}
|
||||
DataFlow::Node getValue() { result = getSsaDefinition().getRhsNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +36,7 @@ module GlobalAccessPath {
|
||||
* (function(ns) {
|
||||
* ns.x; // reference to 'NS.x'
|
||||
* })(NS = NS || {});
|
||||
* ```
|
||||
* ```
|
||||
*/
|
||||
cached
|
||||
string fromReference(DataFlow::Node node) {
|
||||
@@ -59,9 +56,7 @@ module GlobalAccessPath {
|
||||
result = fromReference(prop.getBase()) + "." + prop.getPropertyName()
|
||||
)
|
||||
or
|
||||
exists(Closure::ClosureNamespaceAccess acc | node = acc |
|
||||
result = acc.getClosureNamespace()
|
||||
)
|
||||
exists(Closure::ClosureNamespaceAccess acc | node = acc | result = acc.getClosureNamespace())
|
||||
or
|
||||
exists(PropertyProjection proj | node = proj |
|
||||
proj.isSingletonProjection() and
|
||||
@@ -101,9 +96,7 @@ module GlobalAccessPath {
|
||||
* foo = foo || {};
|
||||
* ```
|
||||
*/
|
||||
private predicate isSelfAssignment(DataFlow::Node rhs) {
|
||||
fromRhs(rhs) = fromReference(rhs)
|
||||
}
|
||||
private predicate isSelfAssignment(DataFlow::Node rhs) { fromRhs(rhs) = fromReference(rhs) }
|
||||
|
||||
/**
|
||||
* Holds if there is an assignment to `accessPath` in `file`, not counting
|
||||
@@ -139,7 +132,7 @@ module GlobalAccessPath {
|
||||
* foo = { bar: class {} };
|
||||
*
|
||||
* (function(f) {
|
||||
* f.bar = class {}
|
||||
* f.bar = class {}
|
||||
* })(foo = foo || {});
|
||||
* ```
|
||||
*/
|
||||
|
||||
@@ -122,9 +122,7 @@ class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent {
|
||||
/** Gets the toplevel in which this tag appears. */
|
||||
TopLevel getTopLevel() { result = getParent().getComment().getTopLevel() }
|
||||
|
||||
override JSDoc getJSDocComment() {
|
||||
result.getATag() = this
|
||||
}
|
||||
override JSDoc getJSDocComment() { result.getATag() = this }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,9 +178,7 @@ class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent, TypeAnnotatio
|
||||
|
||||
override string toString() { jsdoc_type_exprs(this, _, _, _, result) }
|
||||
|
||||
override JSDoc getJSDocComment() {
|
||||
result = getParent().getJSDocComment()
|
||||
}
|
||||
override JSDoc getJSDocComment() { result = getParent().getJSDocComment() }
|
||||
|
||||
override Stmt getEnclosingStmt() {
|
||||
exists(Documentable astNode | astNode.getDocumentation() = getJSDocComment() |
|
||||
@@ -195,9 +191,9 @@ class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent, TypeAnnotatio
|
||||
}
|
||||
|
||||
override StmtContainer getContainer() { result = getEnclosingStmt().getContainer() }
|
||||
|
||||
|
||||
override Function getEnclosingFunction() { result = getContainer() }
|
||||
|
||||
|
||||
override TopLevel getTopLevel() { result = getEnclosingStmt().getTopLevel() }
|
||||
}
|
||||
|
||||
@@ -396,13 +392,9 @@ class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
|
||||
*/
|
||||
JSDocTypeExpr getAnArgument() { result = getArgument(_) }
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
getHead().hasQualifiedName(globalName)
|
||||
}
|
||||
override predicate hasQualifiedName(string globalName) { getHead().hasQualifiedName(globalName) }
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
result = getHead().getClass()
|
||||
}
|
||||
override DataFlow::ClassNode getClass() { result = getHead().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -423,9 +415,7 @@ class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() }
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
result = getTypeExpr().getClass()
|
||||
}
|
||||
override DataFlow::ClassNode getClass() { result = getTypeExpr().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,9 +436,7 @@ class JSDocNonNullableTypeExpr extends @jsdoc_non_nullable_type_expr, JSDocTypeE
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() }
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
result = getTypeExpr().getClass()
|
||||
}
|
||||
override DataFlow::ClassNode getClass() { result = getTypeExpr().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -548,11 +536,11 @@ class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTyp
|
||||
/** Gets the underlying type of this optional type. */
|
||||
JSDocTypeExpr getUnderlyingType() { result = getChild(0) }
|
||||
|
||||
override JSDocTypeExpr getAnUnderlyingType() { result = getUnderlyingType().getAnUnderlyingType() }
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
result = getUnderlyingType().getClass()
|
||||
override JSDocTypeExpr getAnUnderlyingType() {
|
||||
result = getUnderlyingType().getAnUnderlyingType()
|
||||
}
|
||||
|
||||
override DataFlow::ClassNode getClass() { result = getUnderlyingType().getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,9 +92,7 @@ private class ConsPath extends Path, TConsPath {
|
||||
* that is, everything after the last dot. The fourth group includes the dot, the
|
||||
* fifth does not.
|
||||
*/
|
||||
private string pathRegex() {
|
||||
result = "(.*)(?:/|^)(([^/]*?)(\\.([^.]*))?)"
|
||||
}
|
||||
private string pathRegex() { result = "(.*)(?:/|^)(([^/]*?)(\\.([^.]*))?)" }
|
||||
|
||||
/**
|
||||
* A string value that represents a (relative or absolute) file system path.
|
||||
|
||||
@@ -75,11 +75,11 @@ private module ClosurePromise {
|
||||
|
||||
ClosurePromiseTaintStep() {
|
||||
// static methods in goog.Promise
|
||||
exists (DataFlow::CallNode call, string name |
|
||||
exists(DataFlow::CallNode call, string name |
|
||||
call = Closure::moduleImport("goog.Promise." + name).getACall() and
|
||||
this = call and
|
||||
pred = call.getAnArgument()
|
||||
|
|
||||
|
|
||||
name = "all" or
|
||||
name = "allSettled" or
|
||||
name = "firstFulfilled" or
|
||||
@@ -87,15 +87,13 @@ private module ClosurePromise {
|
||||
)
|
||||
or
|
||||
// promise created through goog.promise.withResolver()
|
||||
exists (DataFlow::CallNode resolver |
|
||||
exists(DataFlow::CallNode resolver |
|
||||
resolver = Closure::moduleImport("goog.Promise.withResolver").getACall() and
|
||||
this = resolver.getAPropertyRead("promise") and
|
||||
pred = resolver.getAMethodCall("resolve").getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate step(DataFlow::Node src, DataFlow::Node dst) {
|
||||
src = pred and dst = this
|
||||
}
|
||||
override predicate step(DataFlow::Node src, DataFlow::Node dst) { src = pred and dst = this }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,6 +384,7 @@ private module Internal {
|
||||
rewindReads(bb, i, v) = 1 and result = getDefReachingEndOf(bb.getImmediateDominator(), v)
|
||||
}
|
||||
}
|
||||
|
||||
private import Internal
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,7 +75,6 @@ module StringOps {
|
||||
*/
|
||||
private class StartsWith_IndexOfEquals extends Range, DataFlow::ValueNode {
|
||||
override EqualityTest astNode;
|
||||
|
||||
DataFlow::MethodCallNode indexOf;
|
||||
|
||||
StartsWith_IndexOfEquals() {
|
||||
@@ -118,8 +117,10 @@ module StringOps {
|
||||
StartsWith_Library() {
|
||||
getNumArgument() = 2 and
|
||||
exists(DataFlow::SourceNode callee | this = callee.getACall() |
|
||||
callee = LodashUnderscore::member("startsWith") or
|
||||
callee = DataFlow::moduleMember("ramda", "startsWith") or
|
||||
callee = LodashUnderscore::member("startsWith")
|
||||
or
|
||||
callee = DataFlow::moduleMember("ramda", "startsWith")
|
||||
or
|
||||
exists(string name |
|
||||
callee = Closure::moduleImport("goog.string." + name) and
|
||||
(name = "startsWith" or name = "caseInsensitiveStartsWith")
|
||||
@@ -137,9 +138,7 @@ module StringOps {
|
||||
*/
|
||||
private class StartsWith_FirstCharacter extends Range, DataFlow::ValueNode {
|
||||
override EqualityTest astNode;
|
||||
|
||||
DataFlow::PropRead read;
|
||||
|
||||
Expr constant;
|
||||
|
||||
StartsWith_FirstCharacter() {
|
||||
@@ -161,9 +160,7 @@ module StringOps {
|
||||
*/
|
||||
private class StartsWith_Substring extends Range, DataFlow::ValueNode {
|
||||
override EqualityTest astNode;
|
||||
|
||||
DataFlow::MethodCallNode call;
|
||||
|
||||
DataFlow::Node substring;
|
||||
|
||||
StartsWith_Substring() {
|
||||
@@ -270,7 +267,6 @@ module StringOps {
|
||||
*/
|
||||
private class Includes_IndexOfEquals extends Range, DataFlow::ValueNode {
|
||||
MethodCallExpr indexOf;
|
||||
|
||||
override EqualityTest astNode;
|
||||
|
||||
Includes_IndexOfEquals() {
|
||||
@@ -294,9 +290,7 @@ module StringOps {
|
||||
*/
|
||||
private class Includes_IndexOfRelational extends Range, DataFlow::ValueNode {
|
||||
MethodCallExpr indexOf;
|
||||
|
||||
override RelationalComparison astNode;
|
||||
|
||||
boolean polarity;
|
||||
|
||||
Includes_IndexOfRelational() {
|
||||
@@ -336,7 +330,6 @@ module StringOps {
|
||||
*/
|
||||
private class Includes_IndexOfBitwise extends Range, DataFlow::ValueNode {
|
||||
MethodCallExpr indexOf;
|
||||
|
||||
override BitNotExpr astNode;
|
||||
|
||||
Includes_IndexOfBitwise() {
|
||||
@@ -422,8 +415,10 @@ module StringOps {
|
||||
EndsWith_Library() {
|
||||
getNumArgument() = 2 and
|
||||
exists(DataFlow::SourceNode callee | this = callee.getACall() |
|
||||
callee = LodashUnderscore::member("endsWith") or
|
||||
callee = DataFlow::moduleMember("ramda", "endsWith") or
|
||||
callee = LodashUnderscore::member("endsWith")
|
||||
or
|
||||
callee = DataFlow::moduleMember("ramda", "endsWith")
|
||||
or
|
||||
exists(string name |
|
||||
callee = Closure::moduleImport("goog.string." + name) and
|
||||
(name = "endsWith" or name = "caseInsensitiveEndsWith")
|
||||
@@ -488,49 +483,37 @@ module StringOps {
|
||||
* Gets the `n`th operand of this string concatenation.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationOperand getOperand(int n) {
|
||||
result = StringConcatenation::getOperand(this, n)
|
||||
}
|
||||
ConcatenationOperand getOperand(int n) { result = StringConcatenation::getOperand(this, n) }
|
||||
|
||||
/**
|
||||
* Gets an operand of this string concatenation.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationOperand getAnOperand() {
|
||||
result = StringConcatenation::getAnOperand(this)
|
||||
}
|
||||
ConcatenationOperand getAnOperand() { result = StringConcatenation::getAnOperand(this) }
|
||||
|
||||
/**
|
||||
* Gets the number of operands of this string concatenation.
|
||||
*/
|
||||
pragma[inline]
|
||||
int getNumOperand() {
|
||||
result = StringConcatenation::getNumOperand(this)
|
||||
}
|
||||
int getNumOperand() { result = StringConcatenation::getNumOperand(this) }
|
||||
|
||||
/**
|
||||
* Gets the first operand of this string concatenation.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationOperand getFirstOperand() {
|
||||
result = StringConcatenation::getFirstOperand(this)
|
||||
}
|
||||
ConcatenationOperand getFirstOperand() { result = StringConcatenation::getFirstOperand(this) }
|
||||
|
||||
/**
|
||||
* Gets the last operand of this string concatenation
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationOperand getLastOperand() {
|
||||
result = StringConcatenation::getLastOperand(this)
|
||||
}
|
||||
ConcatenationOperand getLastOperand() { result = StringConcatenation::getLastOperand(this) }
|
||||
|
||||
/**
|
||||
* Holds if this only acts as a string coercion, such as `"" + x`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate isCoercion() {
|
||||
StringConcatenation::isCoercion(this)
|
||||
}
|
||||
predicate isCoercion() { StringConcatenation::isCoercion(this) }
|
||||
|
||||
/**
|
||||
* Holds if this is the root of a concatenation tree, that is,
|
||||
@@ -538,34 +521,26 @@ module StringOps {
|
||||
* another concatenation operator.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate isRoot() {
|
||||
StringConcatenation::isRoot(this)
|
||||
}
|
||||
predicate isRoot() { StringConcatenation::isRoot(this) }
|
||||
|
||||
/**
|
||||
* Holds if this is a leaf in the concatenation tree, that is, it is not
|
||||
* itself a concatenation.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate isLeaf() {
|
||||
not exists(StringConcatenation::getAnOperand(this))
|
||||
}
|
||||
predicate isLeaf() { not exists(StringConcatenation::getAnOperand(this)) }
|
||||
|
||||
/**
|
||||
* Gets the root of the concatenation tree in which this is an operator.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationRoot getRoot() {
|
||||
result = StringConcatenation::getRoot(this)
|
||||
}
|
||||
ConcatenationRoot getRoot() { result = StringConcatenation::getRoot(this) }
|
||||
|
||||
/**
|
||||
* Gets the enclosing concatenation in which this is an operand, if any.
|
||||
*/
|
||||
pragma[inline]
|
||||
Concatenation getParentConcatenation() {
|
||||
this = StringConcatenation::getAnOperand(result)
|
||||
}
|
||||
Concatenation getParentConcatenation() { this = StringConcatenation::getAnOperand(result) }
|
||||
|
||||
/**
|
||||
* Gets the last leaf in this concatenation tree.
|
||||
@@ -573,9 +548,7 @@ module StringOps {
|
||||
* For example, `z` is the last leaf in `x + y + z`.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationLeaf getLastLeaf() {
|
||||
result = StringConcatenation::getLastOperand*(this)
|
||||
}
|
||||
ConcatenationLeaf getLastLeaf() { result = StringConcatenation::getLastOperand*(this) }
|
||||
|
||||
/**
|
||||
* Gets the first leaf in this concatenation tree.
|
||||
@@ -583,9 +556,7 @@ module StringOps {
|
||||
* For example, `x` is the first leaf in `x + y + z`.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationLeaf getFirstLeaf() {
|
||||
result = StringConcatenation::getFirstOperand*(this)
|
||||
}
|
||||
ConcatenationLeaf getFirstLeaf() { result = StringConcatenation::getFirstOperand*(this) }
|
||||
|
||||
/**
|
||||
* Gets the leaf that is occurs immediately before this leaf in the
|
||||
@@ -594,9 +565,7 @@ module StringOps {
|
||||
* For example, `y` is the previous leaf from `z` in `x + y + z`.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationLeaf getPreviousLeaf() {
|
||||
adjacentLeaves(result, this)
|
||||
}
|
||||
ConcatenationLeaf getPreviousLeaf() { adjacentLeaves(result, this) }
|
||||
|
||||
/**
|
||||
* Gets the leaf that is occurs immediately after this leaf in the
|
||||
@@ -605,9 +574,7 @@ module StringOps {
|
||||
* For example, `y` is the next leaf from `x` in `x + y + z`.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationLeaf getNextLeaf() {
|
||||
adjacentLeaves(this, result)
|
||||
}
|
||||
ConcatenationLeaf getNextLeaf() { adjacentLeaves(this, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -626,9 +593,7 @@ module StringOps {
|
||||
*/
|
||||
class Concatenation extends ConcatenationNode {
|
||||
pragma[inline]
|
||||
Concatenation() {
|
||||
exists(StringConcatenation::getAnOperand(this))
|
||||
}
|
||||
Concatenation() { exists(StringConcatenation::getAnOperand(this)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -645,9 +610,7 @@ module StringOps {
|
||||
*/
|
||||
class ConcatenationOperand extends ConcatenationNode {
|
||||
pragma[inline]
|
||||
ConcatenationOperand() {
|
||||
this = StringConcatenation::getAnOperand(_)
|
||||
}
|
||||
ConcatenationOperand() { this = StringConcatenation::getAnOperand(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,17 +627,13 @@ module StringOps {
|
||||
*/
|
||||
class ConcatenationRoot extends Concatenation {
|
||||
pragma[inline]
|
||||
ConcatenationRoot() {
|
||||
isRoot()
|
||||
}
|
||||
ConcatenationRoot() { isRoot() }
|
||||
|
||||
/**
|
||||
* Gets a leaf in this concatenation tree that this node is the root of.
|
||||
*/
|
||||
pragma[inline]
|
||||
ConcatenationLeaf getALeaf() {
|
||||
this = StringConcatenation::getRoot(result)
|
||||
}
|
||||
ConcatenationLeaf getALeaf() { this = StringConcatenation::getRoot(result) }
|
||||
|
||||
/**
|
||||
* Returns the concatenation of all constant operands in this concatenation,
|
||||
@@ -691,11 +650,10 @@ module StringOps {
|
||||
or
|
||||
not exists(getStringValue()) and
|
||||
result = strictconcat(StringLiteralLike leaf |
|
||||
leaf = getALeaf().asExpr()
|
||||
|
|
||||
leaf.getStringValue()
|
||||
order by leaf.getFirstToken().getIndex() asc
|
||||
)
|
||||
leaf = getALeaf().asExpr()
|
||||
|
|
||||
leaf.getStringValue() order by leaf.getFirstToken().getIndex()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -720,9 +678,7 @@ module StringOps {
|
||||
*/
|
||||
class ConcatenationLeaf extends ConcatenationOperand {
|
||||
pragma[inline]
|
||||
ConcatenationLeaf() {
|
||||
isLeaf()
|
||||
}
|
||||
ConcatenationLeaf() { isLeaf() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,9 +695,7 @@ module StringOps {
|
||||
* A data flow node that is part of an HTML string concatenation.
|
||||
*/
|
||||
class HtmlConcatenationNode extends ConcatenationNode {
|
||||
HtmlConcatenationNode() {
|
||||
getRoot() instanceof HtmlConcatenationRoot
|
||||
}
|
||||
HtmlConcatenationNode() { getRoot() instanceof HtmlConcatenationRoot }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -749,8 +703,6 @@ module StringOps {
|
||||
* and is not itself a concatenation operator.
|
||||
*/
|
||||
class HtmlConcatenationLeaf extends ConcatenationLeaf {
|
||||
HtmlConcatenationLeaf() {
|
||||
getRoot() instanceof HtmlConcatenationRoot
|
||||
}
|
||||
HtmlConcatenationLeaf() { getRoot() instanceof HtmlConcatenationRoot }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,9 +551,7 @@ class TypeExpr extends ExprOrType, @typeexpr, TypeAnnotation {
|
||||
|
||||
override TopLevel getTopLevel() { result = ExprOrType.super.getTopLevel() }
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
result.getAstNode() = getType().(ClassType).getClass()
|
||||
}
|
||||
override DataFlow::ClassNode getClass() { result.getAstNode() = getType().(ClassType).getClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1525,7 +1523,6 @@ class TSGlobalDeclImport extends DataFlow::ModuleImportNode::Range {
|
||||
*/
|
||||
class ReferenceImport extends LineComment {
|
||||
string attribute;
|
||||
|
||||
string value;
|
||||
|
||||
ReferenceImport() {
|
||||
@@ -1554,16 +1551,14 @@ class ReferenceImport extends LineComment {
|
||||
*
|
||||
* Gets the file referenced by this import.
|
||||
*/
|
||||
deprecated
|
||||
File getImportedFile() { none() }
|
||||
deprecated File getImportedFile() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED. This is no longer supported.
|
||||
*
|
||||
* Gets the top-level of the referenced file.
|
||||
*/
|
||||
deprecated
|
||||
TopLevel getImportedTopLevel() { none() }
|
||||
deprecated TopLevel getImportedTopLevel() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -447,7 +447,7 @@ class GlobalVarDecl extends VarDecl {
|
||||
|
||||
/**
|
||||
* An array pattern.
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
@@ -456,7 +456,7 @@ class GlobalVarDecl extends VarDecl {
|
||||
* var c;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
*/
|
||||
class ArrayPattern extends DestructuringPattern, @arraypattern {
|
||||
/** Gets the `i`th element of this array pattern. */
|
||||
Expr getElement(int i) {
|
||||
@@ -542,7 +542,7 @@ class ObjectPattern extends DestructuringPattern, @objectpattern {
|
||||
|
||||
/**
|
||||
* A property pattern in an object pattern.
|
||||
*
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
@@ -551,7 +551,7 @@ class ObjectPattern extends DestructuringPattern, @objectpattern {
|
||||
* var c;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
*/
|
||||
class PropertyPattern extends @property, ASTNode {
|
||||
PropertyPattern() {
|
||||
// filter out ordinary properties
|
||||
@@ -831,7 +831,7 @@ class DeclarationSpace extends string {
|
||||
* function id(x: String) : any {
|
||||
* return x;
|
||||
* }
|
||||
* ```
|
||||
* ```
|
||||
*/
|
||||
class LexicalName extends @lexical_name {
|
||||
/** Gets the scope in which this name was declared. */
|
||||
|
||||
@@ -215,14 +215,14 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
*/
|
||||
class XMLAttribute extends @xmlattribute, XMLLocatable {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||
|
||||
@@ -1016,9 +1016,7 @@ private DataFlow::Configuration id(DataFlow::Configuration cfg) { result >= cfg
|
||||
*/
|
||||
class PathNode extends TPathNode {
|
||||
DataFlow::Node nd;
|
||||
|
||||
DataFlow::Configuration cfg;
|
||||
|
||||
PathSummary summary;
|
||||
|
||||
PathNode() { this = MkPathNode(nd, cfg, summary) }
|
||||
|
||||
@@ -35,9 +35,7 @@ module DataFlow {
|
||||
(kind = "call" or kind = "apply")
|
||||
} or
|
||||
TThisNode(StmtContainer f) { f.(Function).getThisBinder() = f or f instanceof TopLevel } or
|
||||
TUnusedParameterNode(SimpleParameter p) {
|
||||
not exists(SSA::definition(p))
|
||||
} or
|
||||
TUnusedParameterNode(SimpleParameter p) { not exists(SSA::definition(p)) } or
|
||||
TDestructuredModuleImportNode(ImportDeclaration decl) {
|
||||
exists(decl.getASpecifier().getImportedName())
|
||||
} or
|
||||
@@ -340,7 +338,6 @@ module DataFlow {
|
||||
*/
|
||||
private class RestPatternNode extends Node, TRestPatternNode {
|
||||
DestructuringPattern pattern;
|
||||
|
||||
Expr rest;
|
||||
|
||||
RestPatternNode() { this = TRestPatternNode(pattern, rest) }
|
||||
@@ -386,7 +383,6 @@ module DataFlow {
|
||||
*/
|
||||
private class ElementPatternNode extends Node, TElementPatternNode {
|
||||
ArrayPattern pattern;
|
||||
|
||||
Expr elt;
|
||||
|
||||
ElementPatternNode() { this = TElementPatternNode(pattern, elt) }
|
||||
@@ -414,7 +410,6 @@ module DataFlow {
|
||||
*/
|
||||
private class ElementNode extends Node, TElementNode {
|
||||
ArrayExpr arr;
|
||||
|
||||
Expr elt;
|
||||
|
||||
ElementNode() { this = TElementNode(arr, elt) }
|
||||
@@ -438,7 +433,6 @@ module DataFlow {
|
||||
*/
|
||||
private class ReflectiveCallNode extends Node, TReflectiveCallNode {
|
||||
MethodCallExpr call;
|
||||
|
||||
string kind;
|
||||
|
||||
ReflectiveCallNode() { this = TReflectiveCallNode(call, kind) }
|
||||
@@ -685,7 +679,7 @@ module DataFlow {
|
||||
exists(Parameter param, Node paramNode |
|
||||
param = prop.getParameter() and
|
||||
parameterNode(paramNode, param)
|
||||
|
|
||||
|
|
||||
result = paramNode
|
||||
or
|
||||
// special case: there is no SSA flow step for unused parameters
|
||||
@@ -807,7 +801,6 @@ module DataFlow {
|
||||
*/
|
||||
private class ImportSpecifierAsPropRead extends PropRead {
|
||||
ImportDeclaration imprt;
|
||||
|
||||
ImportSpecifier spec;
|
||||
|
||||
ImportSpecifierAsPropRead() {
|
||||
@@ -883,9 +876,7 @@ module DataFlow {
|
||||
function.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
override BasicBlock getBasicBlock() {
|
||||
result = function.(ExprOrStmt).getBasicBlock()
|
||||
}
|
||||
override BasicBlock getBasicBlock() { result = function.(ExprOrStmt).getBasicBlock() }
|
||||
|
||||
/**
|
||||
* Gets the function corresponding to this exceptional return node.
|
||||
@@ -909,9 +900,7 @@ module DataFlow {
|
||||
invoke.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
override BasicBlock getBasicBlock() {
|
||||
result = invoke.getBasicBlock()
|
||||
}
|
||||
override BasicBlock getBasicBlock() { result = invoke.getBasicBlock() }
|
||||
|
||||
/**
|
||||
* Gets the invocation corresponding to this exceptional return node.
|
||||
@@ -1053,7 +1042,6 @@ module DataFlow {
|
||||
*/
|
||||
private class ReflectiveCallNodeDef extends CallNodeDef {
|
||||
ExplicitMethodCallNode originalCall;
|
||||
|
||||
string kind;
|
||||
|
||||
ReflectiveCallNodeDef() { this = TReflectiveCallNode(originalCall.asExpr(), kind) }
|
||||
@@ -1115,9 +1103,7 @@ module DataFlow {
|
||||
override string toString() { result = "this" }
|
||||
|
||||
override BasicBlock getBasicBlock() {
|
||||
exists(StmtContainer container | this = TThisNode(container) |
|
||||
result = container.getEntry()
|
||||
)
|
||||
exists(StmtContainer container | this = TThisNode(container) | result = container.getEntry())
|
||||
}
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
@@ -1125,7 +1111,8 @@ module DataFlow {
|
||||
) {
|
||||
// Use the function entry as the location
|
||||
exists(StmtContainer container | this = TThisNode(container) |
|
||||
container.getEntry()
|
||||
container
|
||||
.getEntry()
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
@@ -1154,9 +1141,7 @@ module DataFlow {
|
||||
/**
|
||||
* INTERNAL: Use `parameterNode(Parameter)` instead.
|
||||
*/
|
||||
predicate parameterNode(DataFlow::Node nd, Parameter p) {
|
||||
nd = lvalueNode(p)
|
||||
}
|
||||
predicate parameterNode(DataFlow::Node nd, Parameter p) { nd = lvalueNode(p) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Use `thisNode(StmtContainer container)` instead.
|
||||
@@ -1476,6 +1461,7 @@ module DataFlow {
|
||||
exists(ComprehensionBlock cb | def = cb.getIterator()) and
|
||||
cause = "yield"
|
||||
}
|
||||
|
||||
import Nodes
|
||||
import Sources
|
||||
import TypeInference
|
||||
|
||||
@@ -20,16 +20,14 @@ private predicate isEscape(DataFlow::Node escape, string cause) {
|
||||
or
|
||||
escape = any(ExportDeclaration e).getSourceNode(_) and cause = "export"
|
||||
or
|
||||
exists (WithStmt with, Assignment assign |
|
||||
exists(WithStmt with, Assignment assign |
|
||||
with.mayAffect(assign.getLhs()) and
|
||||
assign.getRhs().flow() = escape and
|
||||
cause = "heap"
|
||||
)
|
||||
}
|
||||
|
||||
private DataFlow::Node getAnEscape() {
|
||||
isEscape(result, _)
|
||||
}
|
||||
private DataFlow::Node getAnEscape() { isEscape(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if `n` can flow to a `this`-variable.
|
||||
|
||||
@@ -77,7 +77,8 @@ class InvokeNode extends DataFlow::SourceNode {
|
||||
* x.push(x, ...args, y, ...more); // 'args' and 'more' are a spread arguments
|
||||
* Array.prototype.push.apply(x, args); // 'args' is a spread argument
|
||||
* ```
|
||||
.*/
|
||||
* .
|
||||
*/
|
||||
DataFlow::Node getASpreadArgument() { result = impl.getASpreadArgument() }
|
||||
|
||||
/** Gets the number of arguments of this invocation, if it can be determined. */
|
||||
@@ -866,13 +867,12 @@ module ClassNode {
|
||||
*/
|
||||
class FunctionStyleClass extends Range, DataFlow::ValueNode {
|
||||
override Function astNode;
|
||||
|
||||
AbstractFunction function;
|
||||
|
||||
FunctionStyleClass() {
|
||||
function.getFunction() = astNode and
|
||||
(
|
||||
exists (DataFlow::PropRef read |
|
||||
exists(DataFlow::PropRef read |
|
||||
read.getPropertyName() = "prototype" and
|
||||
read.getBase().analyze().getAValue() = function
|
||||
)
|
||||
|
||||
@@ -158,9 +158,7 @@ class SourceNode extends DataFlow::Node {
|
||||
/**
|
||||
* Gets a source node whose value is stored in a property of this node.
|
||||
*/
|
||||
DataFlow::SourceNode getAPropertySource() {
|
||||
result.flowsTo(getAPropertyWrite().getRhs())
|
||||
}
|
||||
DataFlow::SourceNode getAPropertySource() { result.flowsTo(getAPropertyWrite().getRhs()) }
|
||||
|
||||
/**
|
||||
* Gets a node that this node may flow to using one heap and/or interprocedural step.
|
||||
@@ -168,9 +166,7 @@ class SourceNode extends DataFlow::Node {
|
||||
* See `TypeTracker` for more details about how to use this.
|
||||
*/
|
||||
pragma[inline]
|
||||
DataFlow::SourceNode track(TypeTracker t2, TypeTracker t) {
|
||||
t = t2.step(this, result)
|
||||
}
|
||||
DataFlow::SourceNode track(TypeTracker t2, TypeTracker t) { t = t2.step(this, result) }
|
||||
|
||||
/**
|
||||
* Gets a node that may flow into this one using one heap and/or interprocedural step.
|
||||
|
||||
@@ -63,7 +63,9 @@ module TaintTracking {
|
||||
*
|
||||
* Holds if the edge from `source` to `sink` is a taint sanitizer for data labelled with `lbl`.
|
||||
*/
|
||||
deprecated predicate isSanitizer(DataFlow::Node source, DataFlow::Node sink, DataFlow::FlowLabel lbl) {
|
||||
deprecated predicate isSanitizer(
|
||||
DataFlow::Node source, DataFlow::Node sink, DataFlow::FlowLabel lbl
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
@@ -309,9 +311,7 @@ module TaintTracking {
|
||||
)
|
||||
or
|
||||
// `array.splice(i, del, e)`: if `e` is tainted, then so is `array`.
|
||||
exists(string name |
|
||||
name = "splice"
|
||||
|
|
||||
exists(string name | name = "splice" |
|
||||
pred = call.getArgument(2) and
|
||||
succ.(DataFlow::SourceNode).getAMethodCall(name) = call
|
||||
)
|
||||
@@ -346,7 +346,6 @@ module TaintTracking {
|
||||
*/
|
||||
private class DictionaryTaintStep extends AdditionalTaintStep, DataFlow::ValueNode {
|
||||
override VarAccess astNode;
|
||||
|
||||
DataFlow::Node source;
|
||||
|
||||
DictionaryTaintStep() {
|
||||
@@ -643,9 +642,7 @@ module TaintTracking {
|
||||
*/
|
||||
class ErrorConstructorTaintStep extends AdditionalTaintStep, DataFlow::InvokeNode {
|
||||
ErrorConstructorTaintStep() {
|
||||
exists(string name |
|
||||
this = DataFlow::globalVarRef(name).getAnInvocation()
|
||||
|
|
||||
exists(string name | this = DataFlow::globalVarRef(name).getAnInvocation() |
|
||||
name = "Error" or
|
||||
name = "EvalError" or
|
||||
name = "RangeError" or
|
||||
@@ -762,7 +759,6 @@ module TaintTracking {
|
||||
/** A check of the form `if(o[x] != undefined)`, which sanitizes `x` in its "then" branch. */
|
||||
class UndefinedCheckSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
|
||||
Expr x;
|
||||
|
||||
override EqualityTest astNode;
|
||||
|
||||
UndefinedCheckSanitizer() {
|
||||
@@ -806,7 +802,6 @@ module TaintTracking {
|
||||
*/
|
||||
class PositiveIndexOfSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
|
||||
MethodCallExpr indexOf;
|
||||
|
||||
override RelationalComparison astNode;
|
||||
|
||||
PositiveIndexOfSanitizer() {
|
||||
@@ -827,21 +822,18 @@ module TaintTracking {
|
||||
}
|
||||
|
||||
/** Gets a variable that is defined exactly once. */
|
||||
private Variable singleDef() {
|
||||
strictcount(result.getADefinition()) = 1
|
||||
}
|
||||
private Variable singleDef() { strictcount(result.getADefinition()) = 1 }
|
||||
|
||||
/** A check of the form `if(x == 'some-constant')`, which sanitizes `x` in its "then" branch. */
|
||||
class ConstantComparison extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
|
||||
Expr x;
|
||||
|
||||
override EqualityTest astNode;
|
||||
|
||||
ConstantComparison() {
|
||||
exists(Expr const |
|
||||
astNode.hasOperands(x, const) |
|
||||
exists(Expr const | astNode.hasOperands(x, const) |
|
||||
// either the other operand is a constant
|
||||
const instanceof ConstantExpr or
|
||||
const instanceof ConstantExpr
|
||||
or
|
||||
// or it's an access to a variable that probably acts as a symbolic constant
|
||||
const = singleDef().getAnAccess()
|
||||
)
|
||||
@@ -859,9 +851,7 @@ module TaintTracking {
|
||||
*/
|
||||
private class SanitizingFunction extends Function {
|
||||
DataFlow::ParameterNode sanitizedParameter;
|
||||
|
||||
SanitizerGuardNode sanitizer;
|
||||
|
||||
boolean sanitizerOutcome;
|
||||
|
||||
SanitizingFunction() {
|
||||
@@ -927,7 +917,6 @@ module TaintTracking {
|
||||
*/
|
||||
private class PostMessageEventSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
|
||||
VarAccess event;
|
||||
|
||||
override EqualityTest astNode;
|
||||
|
||||
PostMessageEventSanitizer() {
|
||||
|
||||
@@ -158,7 +158,7 @@ private module NodeTracking {
|
||||
returnExpr(f, nd, _) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
exists (DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
|
||||
exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
|
||||
flowStep(nd, mid, oldSummary) and
|
||||
reachesReturn(f, mid, newSummary) and
|
||||
summary = oldSummary.append(newSummary)
|
||||
@@ -210,12 +210,13 @@ private module NodeTracking {
|
||||
* Holds if property `prop` of `pred` may flow into `succ` along a path summarized by
|
||||
* `summary`.
|
||||
*/
|
||||
private predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop,
|
||||
PathSummary summary) {
|
||||
private predicate loadStep(
|
||||
DataFlow::Node pred, DataFlow::Node succ, string prop, PathSummary summary
|
||||
) {
|
||||
basicLoadStep(pred, succ, prop) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
exists (Function f, DataFlow::SourceNode parm |
|
||||
exists(Function f, DataFlow::SourceNode parm |
|
||||
argumentPassing(succ, pred, f, parm) and
|
||||
reachesReturn(f, parm.getAPropertyRead(prop), summary)
|
||||
)
|
||||
@@ -246,7 +247,7 @@ private module NodeTracking {
|
||||
private predicate flowThroughProperty(
|
||||
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
|
||||
) {
|
||||
exists (string prop, DataFlow::Node base, PathSummary oldSummary, PathSummary newSummary |
|
||||
exists(string prop, DataFlow::Node base, PathSummary oldSummary, PathSummary newSummary |
|
||||
reachableFromStoreBase(prop, pred, base, oldSummary) and
|
||||
loadStep(base, succ, prop, newSummary) and
|
||||
summary = oldSummary.append(newSummary)
|
||||
|
||||
@@ -57,9 +57,7 @@ class AnalyzedNode extends DataFlow::Node {
|
||||
* instances is also performed.
|
||||
*/
|
||||
cached
|
||||
AbstractValue getAValue() {
|
||||
result = getALocalValue()
|
||||
}
|
||||
AbstractValue getAValue() { result = getALocalValue() }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
|
||||
@@ -144,7 +144,6 @@ private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyNa
|
||||
*/
|
||||
class TypeTracker extends TTypeTracker {
|
||||
Boolean hasCall;
|
||||
|
||||
string prop;
|
||||
|
||||
TypeTracker() { this = MkTypeTracker(hasCall, prop) }
|
||||
@@ -291,7 +290,6 @@ private newtype TTypeBackTracker = MkTypeBackTracker(Boolean hasReturn, Optional
|
||||
*/
|
||||
class TypeBackTracker extends TTypeBackTracker {
|
||||
Boolean hasReturn;
|
||||
|
||||
string prop;
|
||||
|
||||
TypeBackTracker() { this = MkTypeBackTracker(hasReturn, prop) }
|
||||
|
||||
@@ -78,9 +78,7 @@ private newtype TAccessPath =
|
||||
/**
|
||||
* A property access on an access path.
|
||||
*/
|
||||
MkAccessStep(AccessPath base, PropertyName name) {
|
||||
exists(namedPropAccess(base, name, _))
|
||||
}
|
||||
MkAccessStep(AccessPath base, PropertyName name) { exists(namedPropAccess(base, name, _)) }
|
||||
|
||||
/**
|
||||
* A representation of a (nested) property access on an SSA variable or captured variable
|
||||
|
||||
@@ -402,6 +402,7 @@ private module CachedSteps {
|
||||
DataFlow::thisNode(f).hasPropertyWrite(prop, rhs)
|
||||
}
|
||||
}
|
||||
|
||||
import CachedSteps
|
||||
|
||||
/**
|
||||
@@ -431,11 +432,8 @@ newtype TPathSummary =
|
||||
*/
|
||||
class PathSummary extends TPathSummary {
|
||||
Boolean hasReturn;
|
||||
|
||||
Boolean hasCall;
|
||||
|
||||
FlowLabel start;
|
||||
|
||||
FlowLabel end;
|
||||
|
||||
PathSummary() { this = MkPathSummary(hasReturn, hasCall, start, end) }
|
||||
@@ -447,9 +445,7 @@ class PathSummary extends TPathSummary {
|
||||
boolean hasCall() { result = hasCall }
|
||||
|
||||
/** Holds if the path represented by this summary contains no unmatched call or return steps. */
|
||||
predicate isLevel() {
|
||||
hasReturn = false and hasCall = false
|
||||
}
|
||||
predicate isLevel() { hasReturn = false and hasCall = false }
|
||||
|
||||
/** Gets the flow label describing the value at the start of this flow path. */
|
||||
FlowLabel getStartLabel() { result = start }
|
||||
|
||||
@@ -263,7 +263,8 @@ private class AnalyzedAmdImport extends AnalyzedPropertyRead, DataFlow::Node {
|
||||
requireCall = amd.getDefine().getARequireCall() and
|
||||
dep = requireCall.getAnArgument() and
|
||||
this = requireCall.flow()
|
||||
) |
|
||||
)
|
||||
|
|
||||
required = dep.(Import).getImportedModule()
|
||||
)
|
||||
}
|
||||
@@ -290,7 +291,6 @@ private class AnalyzedAmdParameter extends AnalyzedVarDef, @vardecl {
|
||||
*/
|
||||
private class AnalyzedValueExport extends AnalyzedPropertyWrite, DataFlow::ValueNode {
|
||||
ExportDeclaration export;
|
||||
|
||||
string name;
|
||||
|
||||
AnalyzedValueExport() { this = export.getSourceNode(name) }
|
||||
@@ -307,9 +307,7 @@ private class AnalyzedValueExport extends AnalyzedPropertyWrite, DataFlow::Value
|
||||
*/
|
||||
private class AnalyzedVariableExport extends AnalyzedPropertyWrite, DataFlow::ValueNode {
|
||||
ExportDeclaration export;
|
||||
|
||||
string name;
|
||||
|
||||
AnalyzedVarDef varDef;
|
||||
|
||||
AnalyzedVariableExport() {
|
||||
@@ -370,7 +368,6 @@ private class AnalyzedExportAssign extends AnalyzedPropertyWrite, DataFlow::Valu
|
||||
*/
|
||||
private class AnalyzedClosureExportAssign extends AnalyzedPropertyWrite, DataFlow::ValueNode {
|
||||
override AssignExpr astNode;
|
||||
|
||||
Closure::ClosureModule mod;
|
||||
|
||||
AnalyzedClosureExportAssign() { astNode.getLhs() = mod.getExportsVariable().getAReference() }
|
||||
|
||||
@@ -236,16 +236,13 @@ private class TypeInferredCalleeWithAnalyzedReturnFlow extends CallWithNonLocalA
|
||||
* Holds if `call` uses `receiver` as its only receiver value.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate hasDefiniteReceiver(
|
||||
DataFlow::MethodCallNode call, LocalObject receiver
|
||||
) {
|
||||
private predicate hasDefiniteReceiver(DataFlow::MethodCallNode call, LocalObject receiver) {
|
||||
call = receiver.getAMethodCall() and
|
||||
exists (DataFlow::AnalyzedNode receiverNode, AbstractValue abstractCapturedReceiver |
|
||||
exists(DataFlow::AnalyzedNode receiverNode, AbstractValue abstractCapturedReceiver |
|
||||
receiverNode = call.getReceiver() and
|
||||
not receiverNode.getALocalValue().isIndefinite(_) and
|
||||
abstractCapturedReceiver = receiver.analyze().getALocalValue() and
|
||||
forall(DataFlow::AbstractValue v |
|
||||
receiverNode.getALocalValue() = v |
|
||||
forall(DataFlow::AbstractValue v | receiverNode.getALocalValue() = v |
|
||||
v = abstractCapturedReceiver
|
||||
)
|
||||
)
|
||||
@@ -276,4 +273,4 @@ private class TypeInferredMethodWithAnalyzedReturnFlow extends CallWithNonLocalA
|
||||
}
|
||||
|
||||
override AnalyzedFunction getACallee() { result = fun }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,9 +54,7 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
|
||||
*/
|
||||
private class AnalyzedPropertyAccess extends AnalyzedPropertyRead, DataFlow::ValueNode {
|
||||
override PropAccess astNode;
|
||||
|
||||
DataFlow::AnalyzedNode baseNode;
|
||||
|
||||
string propName;
|
||||
|
||||
AnalyzedPropertyAccess() {
|
||||
|
||||
@@ -43,9 +43,7 @@ private class AnalyzedSsaDefinitionNode extends AnalyzedNode, DataFlow::SsaDefin
|
||||
private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition {
|
||||
CallWithNonLocalAnalyzedReturnFlow source;
|
||||
|
||||
SsaDefinitionWithNonLocalFlow() {
|
||||
source = getDef().getSource().flow()
|
||||
}
|
||||
SsaDefinitionWithNonLocalFlow() { source = getDef().getSource().flow() }
|
||||
|
||||
CallWithNonLocalAnalyzedReturnFlow getSource() { result = source }
|
||||
}
|
||||
@@ -56,9 +54,7 @@ private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition {
|
||||
private class AnalyzedSsaDefinitionNodeWithNonLocalAnalysis extends AnalyzedSsaDefinitionNode {
|
||||
override SsaDefinitionWithNonLocalFlow ssa;
|
||||
|
||||
override AbstractValue getAValue() {
|
||||
result = ssa.getSource().getAValue()
|
||||
}
|
||||
override AbstractValue getAValue() { result = ssa.getSource().getAValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,7 +384,6 @@ private predicate nodeBuiltins(Variable var, AbstractValue av) {
|
||||
*/
|
||||
private class AnalyzedGlobalVarUse extends DataFlow::AnalyzedValueNode {
|
||||
GlobalVariable gv;
|
||||
|
||||
AnalyzedGlobal agv;
|
||||
|
||||
AnalyzedGlobalVarUse() {
|
||||
@@ -532,7 +527,6 @@ private class AnalyzedGlobal extends TAnalyzedGlobal {
|
||||
*/
|
||||
private class AnalyzedGlocal extends AnalyzedGlobal, TAnalyzedGlocal {
|
||||
GlobalVariable gv;
|
||||
|
||||
TopLevel tl;
|
||||
|
||||
AnalyzedGlocal() { this = TAnalyzedGlocal(gv, tl) }
|
||||
|
||||
@@ -11,7 +11,6 @@ import semmle.javascript.dependencies.Dependencies
|
||||
*/
|
||||
class DependencySemVer extends string {
|
||||
Dependency dep;
|
||||
|
||||
string normalized;
|
||||
|
||||
DependencySemVer() {
|
||||
|
||||
@@ -132,7 +132,6 @@ DataFlow::CallNode moduleRef(AngularModule m) {
|
||||
class ModuleApiCall extends DataFlow::CallNode {
|
||||
/** The module on which the method is called. */
|
||||
AngularModule mod;
|
||||
|
||||
/** The name of the called method. */
|
||||
string methodName;
|
||||
|
||||
@@ -146,7 +145,6 @@ class ModuleApiCall extends DataFlow::CallNode {
|
||||
|
||||
class ModuleApiCallDependencyInjection extends DependencyInjection {
|
||||
ModuleApiCall call;
|
||||
|
||||
string methodName;
|
||||
|
||||
ModuleApiCallDependencyInjection() {
|
||||
|
||||
@@ -65,7 +65,6 @@ private string getInterpolatedExpressionPattern() { result = "(?<=\\{\\{).*?(?=\
|
||||
*/
|
||||
private class HtmlTextNodeAsNgSourceProvider extends NgSourceProvider, HTML::TextNode {
|
||||
string source;
|
||||
|
||||
int offset;
|
||||
|
||||
HtmlTextNodeAsNgSourceProvider() {
|
||||
@@ -108,7 +107,6 @@ abstract private class HtmlAttributeAsNgSourceProvider extends NgSourceProvider,
|
||||
*/
|
||||
private class HtmlAttributeAsInterpolatedNgSourceProvider extends HtmlAttributeAsNgSourceProvider {
|
||||
string source;
|
||||
|
||||
int offset;
|
||||
|
||||
HtmlAttributeAsInterpolatedNgSourceProvider() {
|
||||
@@ -149,9 +147,7 @@ private class HtmlAttributeAsPlainNgSourceProvider extends HtmlAttributeAsNgSour
|
||||
*/
|
||||
private class TemplateFieldNgSourceProvider extends NgSourceProvider {
|
||||
AngularJS::GeneralDirective directive;
|
||||
|
||||
string source;
|
||||
|
||||
int offset;
|
||||
|
||||
TemplateFieldNgSourceProvider() {
|
||||
@@ -365,6 +361,7 @@ private module Lexer {
|
||||
NgOpToken() { this = MkNgToken(_, _, any(NgOpTokenType t), _) }
|
||||
}
|
||||
}
|
||||
|
||||
private import Lexer
|
||||
|
||||
/**
|
||||
@@ -814,6 +811,7 @@ private module Parser {
|
||||
TNgNumber(NgNumToken t) or
|
||||
TNgEmpty()
|
||||
}
|
||||
|
||||
private import Parser
|
||||
|
||||
/**
|
||||
|
||||
@@ -126,7 +126,6 @@ private DataFlow::PropWrite getAPropertyDependencyInjection(Function function) {
|
||||
*/
|
||||
private class FunctionWithInjectProperty extends InjectableFunction {
|
||||
override Function astNode;
|
||||
|
||||
DataFlow::ArrayCreationNode dependencies;
|
||||
|
||||
FunctionWithInjectProperty() {
|
||||
@@ -164,7 +163,6 @@ private class FunctionWithInjectProperty extends InjectableFunction {
|
||||
*/
|
||||
private class FunctionWithExplicitDependencyAnnotation extends InjectableFunction {
|
||||
DataFlow::FunctionNode function;
|
||||
|
||||
override ArrayExpr astNode;
|
||||
|
||||
FunctionWithExplicitDependencyAnnotation() {
|
||||
|
||||
@@ -252,7 +252,6 @@ abstract class CustomServiceDefinition extends DataFlow::Node {
|
||||
abstract class RecipeDefinition extends DataFlow::CallNode, CustomServiceDefinition,
|
||||
DependencyInjection {
|
||||
string methodName;
|
||||
|
||||
string name;
|
||||
|
||||
RecipeDefinition() {
|
||||
@@ -327,7 +326,6 @@ private predicate isCustomServiceDefinitionOnProvider(
|
||||
*/
|
||||
class ControllerDefinition extends CustomSpecialServiceDefinition {
|
||||
string name;
|
||||
|
||||
DataFlow::SourceNode factoryFunction;
|
||||
|
||||
ControllerDefinition() {
|
||||
@@ -348,7 +346,6 @@ class ControllerDefinition extends CustomSpecialServiceDefinition {
|
||||
*/
|
||||
class FilterDefinition extends CustomSpecialServiceDefinition {
|
||||
string name;
|
||||
|
||||
DataFlow::SourceNode factoryFunction;
|
||||
|
||||
FilterDefinition() {
|
||||
@@ -373,7 +370,6 @@ class FilterDefinition extends CustomSpecialServiceDefinition {
|
||||
*/
|
||||
class DirectiveDefinition extends CustomSpecialServiceDefinition {
|
||||
string name;
|
||||
|
||||
DataFlow::SourceNode factoryFunction;
|
||||
|
||||
DirectiveDefinition() {
|
||||
@@ -413,7 +409,6 @@ private class CustomDirectiveControllerDependencyInjection extends DependencyInj
|
||||
*/
|
||||
class ComponentDefinition extends CustomSpecialServiceDefinition {
|
||||
string name;
|
||||
|
||||
DataFlow::SourceNode config;
|
||||
|
||||
ComponentDefinition() {
|
||||
@@ -441,7 +436,6 @@ class ComponentDefinition extends CustomSpecialServiceDefinition {
|
||||
*/
|
||||
class AnimationDefinition extends CustomSpecialServiceDefinition {
|
||||
string name;
|
||||
|
||||
DataFlow::SourceNode factoryFunction;
|
||||
|
||||
AnimationDefinition() {
|
||||
|
||||
@@ -72,7 +72,6 @@ module AsyncPackage {
|
||||
*/
|
||||
private class WaterfallNextTaskCall extends DataFlow::AdditionalPartialInvokeNode {
|
||||
Waterfall waterfall;
|
||||
|
||||
int n;
|
||||
|
||||
WaterfallNextTaskCall() { this = getLastParameter(waterfall.getTask(n)).getACall() }
|
||||
|
||||
@@ -53,7 +53,6 @@ module Babel {
|
||||
*/
|
||||
class Plugin extends JSONValue {
|
||||
Config cfg;
|
||||
|
||||
string pluginName;
|
||||
|
||||
Plugin() { this = cfg.getPluginConfig(pluginName) }
|
||||
@@ -141,13 +140,9 @@ module Babel {
|
||||
*/
|
||||
private class BabelRootTransformedPathExpr extends PathExpr, Expr {
|
||||
RootImportConfig plugin;
|
||||
|
||||
string rawPath;
|
||||
|
||||
string prefix;
|
||||
|
||||
string mappedPrefix;
|
||||
|
||||
string suffix;
|
||||
|
||||
BabelRootTransformedPathExpr() {
|
||||
|
||||
@@ -106,13 +106,13 @@ module ClientRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of an HTTP request method, in all-lowercase.
|
||||
*/
|
||||
* Gets the name of an HTTP request method, in all-lowercase.
|
||||
*/
|
||||
private string httpMethodName() { result = any(HTTP::RequestMethodName m).toLowerCase() }
|
||||
|
||||
/**
|
||||
* A model of a URL request made using the `request` library.
|
||||
*/
|
||||
* A model of a URL request made using the `request` library.
|
||||
*/
|
||||
class RequestUrlRequest extends ClientRequest::Range, DataFlow::CallNode {
|
||||
boolean promise;
|
||||
|
||||
@@ -145,10 +145,9 @@ module ClientRequest {
|
||||
|
||||
/** Gets the response type from the options passed in. */
|
||||
string getResponseType() {
|
||||
if getOptionArgument(1, "json").mayHaveBooleanValue(true) then
|
||||
result = "json"
|
||||
else
|
||||
result = "text"
|
||||
if getOptionArgument(1, "json").mayHaveBooleanValue(true)
|
||||
then result = "json"
|
||||
else result = "text"
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResponseDataNode(string responseType, boolean pr) {
|
||||
@@ -161,28 +160,26 @@ module ClientRequest {
|
||||
promise = false and
|
||||
pr = false and
|
||||
(
|
||||
result = getCallback([1..2]).getParameter(2)
|
||||
result = getCallback([1 .. 2]).getParameter(2)
|
||||
or
|
||||
result = getCallback([1..2]).getParameter(1).getAPropertyRead("body")
|
||||
result = getCallback([1 .. 2]).getParameter(1).getAPropertyRead("body")
|
||||
)
|
||||
or
|
||||
responseType = "error" and
|
||||
promise = false and
|
||||
pr = false and
|
||||
result = getCallback([1..2]).getParameter(0)
|
||||
result = getCallback([1 .. 2]).getParameter(0)
|
||||
}
|
||||
|
||||
override DataFlow::Node getADataNode() { result = getArgument(1) }
|
||||
}
|
||||
|
||||
/** Gets the string `url` or `uri`. */
|
||||
private string urlPropertyName() {
|
||||
result = "url" or result = "uri"
|
||||
}
|
||||
private string urlPropertyName() { result = "url" or result = "uri" }
|
||||
|
||||
/**
|
||||
* A model of a URL request made using the `axios` library.
|
||||
*/
|
||||
* A model of a URL request made using the `axios` library.
|
||||
*/
|
||||
class AxiosUrlRequest extends ClientRequest::Range {
|
||||
string method;
|
||||
|
||||
@@ -256,8 +253,8 @@ module ClientRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* A model of a URL request made using an implementation of the `fetch` API.
|
||||
*/
|
||||
* A model of a URL request made using an implementation of the `fetch` API.
|
||||
*/
|
||||
class FetchUrlRequest extends ClientRequest::Range {
|
||||
DataFlow::Node url;
|
||||
|
||||
@@ -292,8 +289,8 @@ module ClientRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* A model of a URL request made using the `got` library.
|
||||
*/
|
||||
* A model of a URL request made using the `got` library.
|
||||
*/
|
||||
class GotUrlRequest extends ClientRequest::Range {
|
||||
GotUrlRequest() {
|
||||
exists(string moduleName, DataFlow::SourceNode callee | this = callee.getACall() |
|
||||
@@ -333,28 +330,29 @@ module ClientRequest {
|
||||
}
|
||||
|
||||
/** Holds if the result is a JSON object. */
|
||||
predicate isJson() {
|
||||
getOptionArgument(1, "json").mayHaveBooleanValue(true)
|
||||
}
|
||||
predicate isJson() { getOptionArgument(1, "json").mayHaveBooleanValue(true) }
|
||||
|
||||
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
|
||||
result = this and
|
||||
if isStream() then (
|
||||
if isStream()
|
||||
then
|
||||
responseType = "stream" and
|
||||
promise = false
|
||||
) else if isJson() then (
|
||||
responseType = "json" and
|
||||
promise = true
|
||||
) else (
|
||||
responseType = "text" and
|
||||
promise = true
|
||||
)
|
||||
else
|
||||
if isJson()
|
||||
then (
|
||||
responseType = "json" and
|
||||
promise = true
|
||||
) else (
|
||||
responseType = "text" and
|
||||
promise = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A model of a URL request made using the `superagent` library.
|
||||
*/
|
||||
* A model of a URL request made using the `superagent` library.
|
||||
*/
|
||||
class SuperAgentUrlRequest extends ClientRequest::Range {
|
||||
DataFlow::Node url;
|
||||
|
||||
@@ -460,7 +458,8 @@ module ClientRequest {
|
||||
)
|
||||
or
|
||||
exists(string method | result = getAnAlias().getAMethodCall(method) |
|
||||
method = "getAllResponseHeaders" and responseType = "headers" or
|
||||
method = "getAllResponseHeaders" and responseType = "headers"
|
||||
or
|
||||
method = "getResponseHeader" and responseType = "header"
|
||||
)
|
||||
)
|
||||
@@ -468,14 +467,14 @@ module ClientRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* A model of a URL request made using the `XhrIo` class from the closure library.
|
||||
*/
|
||||
* A model of a URL request made using the `XhrIo` class from the closure library.
|
||||
*/
|
||||
class ClosureXhrIoRequest extends ClientRequest::Range {
|
||||
DataFlow::SourceNode base;
|
||||
boolean static;
|
||||
|
||||
ClosureXhrIoRequest() {
|
||||
exists (DataFlow::SourceNode xhrIo | xhrIo = Closure::moduleImport("goog.net.XhrIo") |
|
||||
exists(DataFlow::SourceNode xhrIo | xhrIo = Closure::moduleImport("goog.net.XhrIo") |
|
||||
static = true and
|
||||
base = xhrIo and
|
||||
this = xhrIo.getAMethodCall("send")
|
||||
@@ -490,9 +489,7 @@ module ClientRequest {
|
||||
|
||||
override DataFlow::Node getHost() { none() }
|
||||
|
||||
override DataFlow::Node getADataNode() {
|
||||
result = getArgument([2 .. 3])
|
||||
}
|
||||
override DataFlow::Node getADataNode() { result = getArgument([2 .. 3]) }
|
||||
|
||||
/** Gets an event listener with `this` bound to this object. */
|
||||
DataFlow::FunctionNode getAnEventListener() {
|
||||
@@ -550,5 +547,4 @@ module ClientRequest {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ module ClosureLibrary {
|
||||
Node pred;
|
||||
|
||||
StringStep() {
|
||||
exists (string name | this = Closure::moduleImport("goog.string." + name).getACall() |
|
||||
exists(string name | this = Closure::moduleImport("goog.string." + name).getACall() |
|
||||
pred = getAnArgument() and
|
||||
(
|
||||
name = "canonicalizeNewlines" or
|
||||
name = "canonicalizeNewlines" or
|
||||
name = "capitalize" or
|
||||
name = "collapseBreakingSpaces" or
|
||||
name = "collapseWhitespace" or
|
||||
|
||||
@@ -30,7 +30,6 @@ private class ComposedFunction extends DataFlow::CallNode {
|
||||
*/
|
||||
private class ComposedFunctionTaintStep extends TaintTracking::AdditionalTaintStep {
|
||||
ComposedFunction composed;
|
||||
|
||||
DataFlow::CallNode call;
|
||||
|
||||
ComposedFunctionTaintStep() {
|
||||
|
||||
@@ -125,9 +125,7 @@ module Connect {
|
||||
t.start() and
|
||||
result = getARouteHandlerExpr().flow().getALocalSource()
|
||||
or
|
||||
exists(DataFlow::TypeBackTracker t2 |
|
||||
result = getARouteHandler(t2).backtrack(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeBackTracker t2 | result = getARouteHandler(t2).backtrack(t2, t))
|
||||
}
|
||||
|
||||
override Expr getServer() { result = server }
|
||||
@@ -159,7 +157,6 @@ module Connect {
|
||||
*/
|
||||
private class RequestInputAccess extends HTTP::RequestInputAccess {
|
||||
RequestExpr request;
|
||||
|
||||
string kind;
|
||||
|
||||
RequestInputAccess() {
|
||||
@@ -181,10 +178,7 @@ module Connect {
|
||||
*/
|
||||
private class TrackedRouteHandlerCandidateWithSetup extends RouteHandler,
|
||||
HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode {
|
||||
|
||||
TrackedRouteHandlerCandidateWithSetup() {
|
||||
this = any(RouteSetup s).getARouteHandler()
|
||||
}
|
||||
TrackedRouteHandlerCandidateWithSetup() { this = any(RouteSetup s).getARouteHandler() }
|
||||
|
||||
override SimpleParameter getRouteHandlerParameter(string kind) {
|
||||
result = getRouteHandlerParameter(astNode, kind)
|
||||
|
||||
@@ -81,6 +81,7 @@ private module AlgorithmNames {
|
||||
|
||||
predicate isWeakPasswordHashingAlgorithm(string name) { none() }
|
||||
}
|
||||
|
||||
private import AlgorithmNames
|
||||
|
||||
/**
|
||||
@@ -135,7 +136,6 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm {
|
||||
*/
|
||||
class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm {
|
||||
string name;
|
||||
|
||||
boolean isWeak;
|
||||
|
||||
HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) }
|
||||
@@ -150,7 +150,6 @@ class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm {
|
||||
*/
|
||||
class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm {
|
||||
string name;
|
||||
|
||||
boolean isWeak;
|
||||
|
||||
EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) }
|
||||
@@ -165,7 +164,6 @@ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm
|
||||
*/
|
||||
class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm {
|
||||
string name;
|
||||
|
||||
boolean isWeak;
|
||||
|
||||
PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) }
|
||||
@@ -210,7 +208,6 @@ class CryptographicKeyCredentialsExpr extends CredentialsExpr {
|
||||
private module AsmCrypto {
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
|
||||
Apply() {
|
||||
@@ -250,7 +247,6 @@ private module BrowserIdCrypto {
|
||||
|
||||
private class Apply extends CryptographicOperation {
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
@@ -424,7 +420,6 @@ private module CryptoJS {
|
||||
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
|
||||
Apply() {
|
||||
@@ -463,9 +458,7 @@ private module CryptoJS {
|
||||
private module TweetNaCl {
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm;
|
||||
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
@@ -527,9 +520,7 @@ private module HashJs {
|
||||
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
@@ -572,7 +563,6 @@ private module Forge {
|
||||
|
||||
private class KeyCipher extends Cipher {
|
||||
DataFlow::Node key;
|
||||
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
|
||||
KeyCipher() {
|
||||
@@ -631,9 +621,7 @@ private module Forge {
|
||||
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
@@ -661,9 +649,7 @@ private module Forge {
|
||||
private module Md5 {
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm;
|
||||
|
||||
CallExpr call;
|
||||
|
||||
Apply() {
|
||||
@@ -689,9 +675,7 @@ private module Md5 {
|
||||
private module Bcrypt {
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm;
|
||||
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
@@ -726,9 +710,7 @@ private module Bcrypt {
|
||||
private module Hasha {
|
||||
private class Apply extends CryptographicOperation {
|
||||
Expr input;
|
||||
|
||||
CryptographicAlgorithm algorithm;
|
||||
|
||||
CallExpr call;
|
||||
|
||||
Apply() {
|
||||
|
||||
@@ -102,7 +102,6 @@ module Electron {
|
||||
*/
|
||||
class Callback extends DataFlow::FunctionNode {
|
||||
DataFlow::Node channel;
|
||||
|
||||
Process process;
|
||||
|
||||
Callback() {
|
||||
@@ -139,11 +138,8 @@ module Electron {
|
||||
*/
|
||||
class DirectMessage extends Message {
|
||||
DataFlow::MethodCallNode mc;
|
||||
|
||||
Process process;
|
||||
|
||||
DataFlow::Node channel;
|
||||
|
||||
boolean isSync;
|
||||
|
||||
DirectMessage() {
|
||||
@@ -178,7 +174,6 @@ module Electron {
|
||||
*/
|
||||
class AsyncReplyMessage extends Message {
|
||||
Callback callback;
|
||||
|
||||
DataFlow::Node channel;
|
||||
|
||||
AsyncReplyMessage() {
|
||||
|
||||
@@ -35,9 +35,7 @@ module Express {
|
||||
/**
|
||||
* Holds if `e` may refer to the given `router` object.
|
||||
*/
|
||||
private predicate isRouter(Expr e, RouterDefinition router) {
|
||||
router.flowsTo(e)
|
||||
}
|
||||
private predicate isRouter(Expr e, RouterDefinition router) { router.flowsTo(e) }
|
||||
|
||||
/**
|
||||
* Holds if `e` may refer to a router object.
|
||||
@@ -161,7 +159,6 @@ module Express {
|
||||
*/
|
||||
class RouteHandlerExpr extends Expr {
|
||||
RouteSetup setup;
|
||||
|
||||
int index;
|
||||
|
||||
RouteHandlerExpr() { this = setup.getRouteHandlerExpr(index) }
|
||||
@@ -337,8 +334,7 @@ module Express {
|
||||
}
|
||||
|
||||
/** An Express response source. */
|
||||
abstract private class ResponseSource extends HTTP::Servers::ResponseSource {
|
||||
}
|
||||
abstract private class ResponseSource extends HTTP::Servers::ResponseSource { }
|
||||
|
||||
/**
|
||||
* An Express response source, that is, the response parameter of a
|
||||
@@ -363,16 +359,13 @@ module Express {
|
||||
* An Express response source, based on static type information.
|
||||
*/
|
||||
private class TypedResponseSource extends ResponseSource {
|
||||
TypedResponseSource() {
|
||||
hasUnderlyingType("express", "Response")
|
||||
}
|
||||
TypedResponseSource() { hasUnderlyingType("express", "Response") }
|
||||
|
||||
override RouteHandler getRouteHandler() { none() } // Not known.
|
||||
}
|
||||
|
||||
/** An Express request source. */
|
||||
abstract private class RequestSource extends HTTP::Servers::RequestSource {
|
||||
}
|
||||
abstract private class RequestSource extends HTTP::Servers::RequestSource { }
|
||||
|
||||
/**
|
||||
* An Express request source, that is, the request parameter of a
|
||||
@@ -393,9 +386,7 @@ module Express {
|
||||
* An Express request source, based on static type information.
|
||||
*/
|
||||
private class TypedRequestSource extends RequestSource {
|
||||
TypedRequestSource() {
|
||||
hasUnderlyingType("express", "Request")
|
||||
}
|
||||
TypedRequestSource() { hasUnderlyingType("express", "Request") }
|
||||
|
||||
override RouteHandler getRouteHandler() { none() } // Not known.
|
||||
}
|
||||
@@ -419,7 +410,6 @@ module Express {
|
||||
*/
|
||||
class RequestInputAccess extends HTTP::RequestInputAccess {
|
||||
RouteHandler rh;
|
||||
|
||||
string kind;
|
||||
|
||||
RequestInputAccess() {
|
||||
@@ -593,7 +583,6 @@ module Express {
|
||||
*/
|
||||
class SetMultipleHeaders extends ExplicitHeader, DataFlow::ValueNode {
|
||||
override MethodCallExpr astNode;
|
||||
|
||||
RouteHandler rh;
|
||||
|
||||
SetMultipleHeaders() {
|
||||
@@ -704,9 +693,7 @@ module Express {
|
||||
t.start() and
|
||||
result = DataFlow::exprNode(this)
|
||||
or
|
||||
exists(string name |
|
||||
result = ref(t.continue()).getAMethodCall(name)
|
||||
|
|
||||
exists(string name | result = ref(t.continue()).getAMethodCall(name) |
|
||||
name = "route" or
|
||||
name = routeSetupMethodName()
|
||||
)
|
||||
@@ -717,9 +704,7 @@ module Express {
|
||||
/**
|
||||
* Holds if `sink` may refer to this router.
|
||||
*/
|
||||
predicate flowsTo(Expr sink) {
|
||||
ref(DataFlow::TypeTracker::end()).flowsToExpr(sink)
|
||||
}
|
||||
predicate flowsTo(Expr sink) { ref(DataFlow::TypeTracker::end()).flowsToExpr(sink) }
|
||||
|
||||
/**
|
||||
* Gets a `RouteSetup` that was used for setting up a route on this router.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about code using the Firebase API.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
module Firebase {
|
||||
@@ -15,15 +16,11 @@ module Firebase {
|
||||
result = DataFlow::globalVarRef("firebase")
|
||||
)
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = firebase(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = firebase(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `firebase/app` or `firebase-admin` API object. */
|
||||
DataFlow::SourceNode firebase() {
|
||||
result = firebase(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode firebase() { result = firebase(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a reference to a Firebase app created with `initializeApp`. */
|
||||
private DataFlow::SourceNode initApp(DataFlow::TypeTracker t) {
|
||||
@@ -33,9 +30,7 @@ module Firebase {
|
||||
t.start() and
|
||||
result.hasUnderlyingType("firebase", "app.App")
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = initApp(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = initApp(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,11 +38,11 @@ module Firebase {
|
||||
* app created explicitly with `initializeApp()`.
|
||||
*/
|
||||
DataFlow::SourceNode app() {
|
||||
result = firebase(DataFlow::TypeTracker::end()) or result = initApp(DataFlow::TypeTracker::end())
|
||||
result = firebase(DataFlow::TypeTracker::end()) or
|
||||
result = initApp(DataFlow::TypeTracker::end())
|
||||
}
|
||||
|
||||
module Database {
|
||||
|
||||
/** Gets a reference to a Firebase database object, such as `firebase.database()`. */
|
||||
private DataFlow::SourceNode database(DataFlow::TypeTracker t) {
|
||||
result = app().getAMethodCall("database") and t.start()
|
||||
@@ -55,31 +50,27 @@ module Firebase {
|
||||
t.start() and
|
||||
result.hasUnderlyingType("firebase", "database.Database")
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = database(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = database(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to a Firebase database object, such as `firebase.database()`. */
|
||||
DataFlow::SourceNode database() {
|
||||
result = database(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode database() { result = database(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a node that refers to a `Reference` object, such as `firebase.database().ref()`. */
|
||||
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
(
|
||||
exists (string name | result = database().getAMethodCall(name) |
|
||||
exists(string name | result = database().getAMethodCall(name) |
|
||||
name = "ref" or
|
||||
name = "refFromURL"
|
||||
)
|
||||
or
|
||||
exists (string name | result = ref().getAMethodCall(name) |
|
||||
exists(string name | result = ref().getAMethodCall(name) |
|
||||
name = "push" or
|
||||
name = "child"
|
||||
)
|
||||
or
|
||||
exists (string name | result = ref().getAPropertyRead(name) |
|
||||
exists(string name | result = ref().getAPropertyRead(name) |
|
||||
name = "parent" or
|
||||
name = "root"
|
||||
)
|
||||
@@ -89,15 +80,11 @@ module Firebase {
|
||||
result.hasUnderlyingType("firebase", "database.Reference")
|
||||
)
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = ref(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a node that refers to a `Reference` object, such as `firebase.database().ref()`. */
|
||||
DataFlow::SourceNode ref() {
|
||||
result = ref(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a node that refers to a `Query` or `Reference` object. */
|
||||
private DataFlow::SourceNode query(DataFlow::TypeTracker t) {
|
||||
@@ -105,7 +92,7 @@ module Firebase {
|
||||
(
|
||||
result = ref(t) // a Reference can be used as a Query
|
||||
or
|
||||
exists (string name | result = query().getAMethodCall(name) |
|
||||
exists(string name | result = query().getAMethodCall(name) |
|
||||
name = "endAt" or
|
||||
name = "limitTo" + any(string s) or
|
||||
name = "orderBy" + any(string s) or
|
||||
@@ -115,15 +102,11 @@ module Firebase {
|
||||
result.hasUnderlyingType("firebase", "database.Query")
|
||||
)
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = query(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = query(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a node that refers to a `Query` or `Reference` object. */
|
||||
DataFlow::SourceNode query() {
|
||||
result = query(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode query() { result = query(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/**
|
||||
* A call of form `query.on(...)` or `query.once(...)`.
|
||||
@@ -137,9 +120,7 @@ module Firebase {
|
||||
/**
|
||||
* Gets the argument in which the callback is passed.
|
||||
*/
|
||||
DataFlow::Node getCallbackNode() {
|
||||
result = getArgument(1)
|
||||
}
|
||||
DataFlow::Node getCallbackNode() { result = getArgument(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,9 +130,7 @@ module Firebase {
|
||||
t.start() and
|
||||
result = ref().getAMethodCall("transaction").getArgument(0).getALocalSource()
|
||||
or
|
||||
exists (DataFlow::TypeBackTracker t2 |
|
||||
result = transactionCallback(t2).backtrack(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeBackTracker t2 | result = transactionCallback(t2).backtrack(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,45 +151,33 @@ module Firebase {
|
||||
t.start() and
|
||||
result = DataFlow::moduleImport("firebase-functions")
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = namespace(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = namespace(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the Cloud Functions namespace. */
|
||||
DataFlow::SourceNode namespace() {
|
||||
result = namespace(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode namespace() { result = namespace(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a reference to a Cloud Functions database object. */
|
||||
private DataFlow::SourceNode database(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = namespace().getAPropertyRead("database")
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = database(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = database(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to a Cloud Functions database object. */
|
||||
DataFlow::SourceNode database() {
|
||||
result = database(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode database() { result = database(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a data flow node holding a `RefBuilder` object. */
|
||||
private DataFlow::SourceNode refBuilder(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = database().getAMethodCall("ref")
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = refBuilder(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = refBuilder(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a data flow node holding a `RefBuilder` object. */
|
||||
DataFlow::SourceNode ref() {
|
||||
result = refBuilder(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode ref() { result = refBuilder(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a call that registers a listener on a `RefBuilder`, such as `ref.onCreate(...)`. */
|
||||
class RefBuilderListenCall extends DataFlow::MethodCallNode {
|
||||
@@ -222,16 +189,16 @@ module Firebase {
|
||||
/**
|
||||
* Gets the data flow node holding the listener callback.
|
||||
*/
|
||||
DataFlow::Node getCallbackNode() {
|
||||
result = getArgument(0)
|
||||
}
|
||||
DataFlow::Node getCallbackNode() { result = getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a Firebase method that sets up a route.
|
||||
*/
|
||||
private class RouteSetup extends HTTP::Servers::StandardRouteSetup, CallExpr {
|
||||
RouteSetup() { this = namespace().getAPropertyRead("https").getAMemberCall("onRequest").asExpr() }
|
||||
RouteSetup() {
|
||||
this = namespace().getAPropertyRead("https").getAMemberCall("onRequest").asExpr()
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getARouteHandler() {
|
||||
result = getARouteHandler(DataFlow::TypeBackTracker::end())
|
||||
@@ -251,15 +218,15 @@ module Firebase {
|
||||
* A function used as a route handler.
|
||||
*/
|
||||
private class RouteHandler extends Express::RouteHandler, HTTP::Servers::StandardRouteHandler,
|
||||
DataFlow::ValueNode {
|
||||
DataFlow::ValueNode {
|
||||
RouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
|
||||
|
||||
override SimpleParameter getRouteHandlerParameter(string kind) {
|
||||
kind = "request" and result = this.(DataFlow::FunctionNode).getParameter(0).getParameter() or
|
||||
kind = "request" and result = this.(DataFlow::FunctionNode).getParameter(0).getParameter()
|
||||
or
|
||||
kind = "response" and result = this.(DataFlow::FunctionNode).getParameter(1).getParameter()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,9 +240,7 @@ module Firebase {
|
||||
result = any(CloudFunctions::RefBuilderListenCall call).getCallbackNode().getALocalSource()
|
||||
)
|
||||
or
|
||||
exists (DataFlow::TypeBackTracker t2 |
|
||||
result = snapshotCallback(t2).backtrack(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeBackTracker t2 | result = snapshotCallback(t2).backtrack(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,7 +265,7 @@ module Firebase {
|
||||
or
|
||||
result = snapshot().getAMethodCall("forEach").getCallback(0).getParameter(0)
|
||||
or
|
||||
exists (string prop | result = snapshot().getAPropertyRead(prop) |
|
||||
exists(string prop | result = snapshot().getAPropertyRead(prop) |
|
||||
prop = "before" or // only defined on Change objects
|
||||
prop = "after"
|
||||
)
|
||||
@@ -310,25 +275,21 @@ module Firebase {
|
||||
or
|
||||
promiseTaintStep(snapshot(t), result)
|
||||
or
|
||||
exists (DataFlow::TypeTracker t2 |
|
||||
result = snapshot(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = snapshot(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to a `DataSnapshot` value, such as `x` in
|
||||
* `firebase.database().ref().on('value', x => {...})`.
|
||||
*/
|
||||
DataFlow::SourceNode snapshot() {
|
||||
result = snapshot(DataFlow::TypeTracker::end())
|
||||
}
|
||||
DataFlow::SourceNode snapshot() { result = snapshot(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/**
|
||||
* A reference to a value obtained from a Firebase database.
|
||||
*/
|
||||
class FirebaseVal extends RemoteFlowSource {
|
||||
FirebaseVal() {
|
||||
exists (string name | this = snapshot().getAMethodCall(name) |
|
||||
exists(string name | this = snapshot().getAMethodCall(name) |
|
||||
name = "val" or
|
||||
name = "exportVal"
|
||||
)
|
||||
@@ -336,8 +297,6 @@ module Firebase {
|
||||
this = Database::transactionCallback().(DataFlow::FunctionNode).getParameter(0)
|
||||
}
|
||||
|
||||
override string getSourceType() {
|
||||
result = "Firebase database"
|
||||
}
|
||||
override string getSourceType() { result = "Firebase database" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ module Hapi {
|
||||
*/
|
||||
private class RequestInputAccess extends HTTP::RequestInputAccess {
|
||||
RouteHandler rh;
|
||||
|
||||
string kind;
|
||||
|
||||
RequestInputAccess() {
|
||||
@@ -176,7 +175,6 @@ module Hapi {
|
||||
*/
|
||||
class RouteSetup extends MethodCallExpr, HTTP::Servers::StandardRouteSetup {
|
||||
ServerDefinition server;
|
||||
|
||||
Expr handler;
|
||||
|
||||
RouteSetup() {
|
||||
@@ -200,9 +198,7 @@ module Hapi {
|
||||
t.start() and
|
||||
result = handler.flow().getALocalSource()
|
||||
or
|
||||
exists(DataFlow::TypeBackTracker t2 |
|
||||
result = getARouteHandler(t2).backtrack(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeBackTracker t2 | result = getARouteHandler(t2).backtrack(t2, t))
|
||||
}
|
||||
|
||||
Expr getRouteHandlerExpr() { result = handler }
|
||||
@@ -236,8 +232,6 @@ module Hapi {
|
||||
*/
|
||||
private class TrackedRouteHandlerCandidateWithSetup extends RouteHandler,
|
||||
HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode {
|
||||
TrackedRouteHandlerCandidateWithSetup() {
|
||||
this = any(RouteSetup s).getARouteHandler()
|
||||
}
|
||||
TrackedRouteHandlerCandidateWithSetup() { this = any(RouteSetup s).getARouteHandler() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Provides classes for working with [Koa](https://koajs.com) applications.
|
||||
*/
|
||||
@@ -91,17 +90,13 @@ module Koa {
|
||||
*/
|
||||
RouteHandler getRouteHandler() { result = rh }
|
||||
|
||||
predicate flowsTo(DataFlow::Node nd) {
|
||||
ref(DataFlow::TypeTracker::end()).flowsTo(nd)
|
||||
}
|
||||
predicate flowsTo(DataFlow::Node nd) { ref(DataFlow::TypeTracker::end()).flowsTo(nd) }
|
||||
|
||||
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = this
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
result = ref(t2).track(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +163,6 @@ module Koa {
|
||||
*/
|
||||
private class RequestInputAccess extends HTTP::RequestInputAccess {
|
||||
RouteHandler rh;
|
||||
|
||||
string kind;
|
||||
|
||||
RequestInputAccess() {
|
||||
|
||||
@@ -366,15 +366,12 @@ module LodashUnderscore {
|
||||
*/
|
||||
private class ExceptionStep extends DataFlow::CallNode, DataFlow::AdditionalFlowStep {
|
||||
ExceptionStep() {
|
||||
exists(string name |
|
||||
this = member(name).getACall()
|
||||
|
|
||||
exists(string name | this = member(name).getACall() |
|
||||
// Members ending with By, With, or While indicate that they are a variant of
|
||||
// another function that takes a callback.
|
||||
name.matches("%By") or
|
||||
name.matches("%With") or
|
||||
name.matches("%While") or
|
||||
|
||||
// Other members that don't fit the above pattern.
|
||||
name = "each" or
|
||||
name = "eachRight" or
|
||||
|
||||
@@ -53,7 +53,6 @@ private module MongoDB {
|
||||
/** A call to a MongoDB query method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::ValueNode {
|
||||
override MethodCallExpr astNode;
|
||||
|
||||
int queryArgIdx;
|
||||
|
||||
QueryCall() {
|
||||
|
||||
@@ -136,7 +136,6 @@ module NodeJSLib {
|
||||
*/
|
||||
private class RequestInputAccess extends HTTP::RequestInputAccess {
|
||||
RequestExpr request;
|
||||
|
||||
string kind;
|
||||
|
||||
RequestInputAccess() {
|
||||
@@ -190,7 +189,6 @@ module NodeJSLib {
|
||||
|
||||
class RouteSetup extends CallExpr, HTTP::Servers::StandardRouteSetup {
|
||||
ServerDefinition server;
|
||||
|
||||
Expr handler;
|
||||
|
||||
RouteSetup() {
|
||||
@@ -527,7 +525,6 @@ module NodeJSLib {
|
||||
*/
|
||||
private class FileStreamRead extends FileSystemReadAccess, DataFlow::CallNode {
|
||||
NodeJSFileSystemAccess stream;
|
||||
|
||||
string method;
|
||||
|
||||
FileStreamRead() {
|
||||
@@ -773,7 +770,6 @@ module NodeJSLib {
|
||||
*/
|
||||
class ClientRequestHandler extends DataFlow::FunctionNode {
|
||||
string handledEvent;
|
||||
|
||||
NodeJSClientRequest clientRequest;
|
||||
|
||||
ClientRequestHandler() {
|
||||
|
||||
@@ -70,9 +70,7 @@ deprecated class CustomPropertyProjection = PropertyProjection::Range;
|
||||
*/
|
||||
private class SimplePropertyProjection extends PropertyProjection::Range {
|
||||
int objectIndex;
|
||||
|
||||
int selectorIndex;
|
||||
|
||||
boolean singleton;
|
||||
|
||||
SimplePropertyProjection() {
|
||||
|
||||
@@ -463,7 +463,6 @@ private class CreateElementDefinition extends ReactElementDefinition {
|
||||
*/
|
||||
private class FactoryDefinition extends ReactElementDefinition {
|
||||
DataFlow::MethodCallNode factory;
|
||||
|
||||
DataFlow::CallNode call;
|
||||
|
||||
FactoryDefinition() {
|
||||
|
||||
@@ -87,7 +87,6 @@ module Restify {
|
||||
*/
|
||||
private class RequestInputAccess extends HTTP::RequestInputAccess {
|
||||
RequestExpr request;
|
||||
|
||||
string kind;
|
||||
|
||||
RequestInputAccess() {
|
||||
|
||||
@@ -14,7 +14,6 @@ module SQL {
|
||||
*/
|
||||
abstract class SqlSanitizer extends Expr {
|
||||
Expr input;
|
||||
|
||||
Expr output;
|
||||
|
||||
/** Gets the input expression being sanitized. */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Models the `shelljs` library in terms of `FileSystemAccess` and `SystemCommandExecution`.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
module ShellJS {
|
||||
@@ -171,12 +172,8 @@ module ShellJS {
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result = getArgument(0)
|
||||
}
|
||||
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
|
||||
|
||||
override DataFlow::Node getADataNode() {
|
||||
result = getReceiver()
|
||||
}
|
||||
override DataFlow::Node getADataNode() { result = getReceiver() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,9 +212,7 @@ module SocketIO {
|
||||
string getEventName() { getArgument(0).mayHaveStringValue(result) }
|
||||
|
||||
/** Gets the callback that handles data received from a client. */
|
||||
private DataFlow::FunctionNode getListener() {
|
||||
result = getCallback(1)
|
||||
}
|
||||
private DataFlow::FunctionNode getListener() { result = getCallback(1) }
|
||||
|
||||
/** Gets the `i`th parameter through which data is received from a client. */
|
||||
DataFlow::SourceNode getReceivedItem(int i) {
|
||||
@@ -256,7 +254,6 @@ module SocketIO {
|
||||
*/
|
||||
class SendNode extends DataFlow::MethodCallNode {
|
||||
DataFlow::SourceNode base;
|
||||
|
||||
int firstDataIndex;
|
||||
|
||||
SendNode() {
|
||||
@@ -370,7 +367,6 @@ module SocketIO {
|
||||
/** A socket.io namespace. */
|
||||
class NamespaceObject extends TNamespace {
|
||||
ServerObject srv;
|
||||
|
||||
string path;
|
||||
|
||||
NamespaceObject() { this = MkNamespace(srv, path) }
|
||||
@@ -488,9 +484,7 @@ module SocketIOClient {
|
||||
t.start() and
|
||||
result = getArgument(1).getALocalSource()
|
||||
or
|
||||
exists(DataFlow::TypeBackTracker t2 |
|
||||
result = getListener(t2).backtrack(t2, t)
|
||||
)
|
||||
exists(DataFlow::TypeBackTracker t2 | result = getListener(t2).backtrack(t2, t))
|
||||
}
|
||||
|
||||
/** Gets the callback that handles data received from the server. */
|
||||
@@ -527,7 +521,6 @@ module SocketIOClient {
|
||||
*/
|
||||
class SendNode extends DataFlow::MethodCallNode {
|
||||
SocketNode base;
|
||||
|
||||
int firstDataIndex;
|
||||
|
||||
SendNode() {
|
||||
@@ -605,7 +598,6 @@ private module EventEmitter {
|
||||
/** A data flow step through socket.io sockets. */
|
||||
private class SocketIoStep extends DataFlow::AdditionalFlowStep {
|
||||
DataFlow::Node pred;
|
||||
|
||||
DataFlow::Node succ;
|
||||
|
||||
SocketIoStep() {
|
||||
|
||||
@@ -26,7 +26,6 @@ abstract class PrintfStyleCall extends DataFlow::CallNode {
|
||||
|
||||
private class LibraryFormatter extends PrintfStyleCall {
|
||||
int formatIndex;
|
||||
|
||||
boolean returns;
|
||||
|
||||
LibraryFormatter() {
|
||||
|
||||
@@ -377,7 +377,6 @@ private module ClosureLibraryUri {
|
||||
*/
|
||||
private class SetterCall extends DataFlow::MethodCallNode, UriLibraryStep {
|
||||
DataFlow::NewNode uri;
|
||||
|
||||
string name;
|
||||
|
||||
SetterCall() {
|
||||
|
||||
@@ -280,7 +280,6 @@ module Vue {
|
||||
*/
|
||||
class ExtendedInstance extends Instance, MkExtendedInstance {
|
||||
VueExtend extend;
|
||||
|
||||
DataFlow::NewNode sub;
|
||||
|
||||
ExtendedInstance() { this = MkExtendedInstance(extend, sub) }
|
||||
|
||||
@@ -108,7 +108,6 @@ private class JQueryParseXmlCall extends XML::ParserInvocation {
|
||||
*/
|
||||
private class JQueryDomElementDefinition extends DOM::ElementDefinition, @callexpr {
|
||||
string tagName;
|
||||
|
||||
CallExpr call;
|
||||
|
||||
JQueryDomElementDefinition() {
|
||||
@@ -147,7 +146,6 @@ abstract private class JQueryAttributeDefinition extends DOM::AttributeDefinitio
|
||||
*/
|
||||
private class JQueryAttributeDefinitionInElement extends JQueryAttributeDefinition {
|
||||
JQueryDomElementDefinition elt;
|
||||
|
||||
DataFlow::PropWrite pwn;
|
||||
|
||||
JQueryAttributeDefinitionInElement() {
|
||||
@@ -205,7 +203,6 @@ private predicate bulkAttributeInit(
|
||||
*/
|
||||
private class JQueryAttrCall extends JQueryAttributeDefinition, @callexpr {
|
||||
JQueryDomElementDefinition elt;
|
||||
|
||||
DataFlow::PropWrite pwn;
|
||||
|
||||
JQueryAttrCall() {
|
||||
|
||||
@@ -69,6 +69,7 @@ module HeuristicNames {
|
||||
result = "(?is).*(redact|censor|obfuscate|hash|md5|sha|((?<!un)(en))?(crypt|code)).*"
|
||||
}
|
||||
}
|
||||
|
||||
private import HeuristicNames
|
||||
|
||||
/** An expression that might contain sensitive data. */
|
||||
|
||||
@@ -83,17 +83,14 @@ module TaintedObject {
|
||||
/**
|
||||
* Sanitizer guard that blocks deep object taint.
|
||||
*/
|
||||
abstract class SanitizerGuard extends TaintTracking::LabeledSanitizerGuardNode {
|
||||
}
|
||||
abstract class SanitizerGuard extends TaintTracking::LabeledSanitizerGuardNode { }
|
||||
|
||||
/**
|
||||
* A test of form `typeof x === "something"`, preventing `x` from being an object in some cases.
|
||||
*/
|
||||
private class TypeTestGuard extends SanitizerGuard, ValueNode {
|
||||
override EqualityTest astNode;
|
||||
|
||||
TypeofExpr typeof;
|
||||
|
||||
boolean polarity;
|
||||
|
||||
TypeTestGuard() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* bypass of sensitive action guards, as well as extension points for
|
||||
* adding your own.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.security.SensitiveActions
|
||||
|
||||
|
||||
@@ -37,9 +37,7 @@ DataFlow::SourceNode document() { result = DOM::documentRef() }
|
||||
predicate isDocument(Expr e) { DOM::documentRef().flowsToExpr(e) }
|
||||
|
||||
/** Holds if `e` could refer to the document URL. */
|
||||
predicate isDocumentURL(Expr e) {
|
||||
e.flow() = DOM::locationSource()
|
||||
}
|
||||
predicate isDocumentURL(Expr e) { e.flow() = DOM::locationSource() }
|
||||
|
||||
/**
|
||||
* Holds if `pacc` accesses a part of `document.location` that is
|
||||
@@ -87,9 +85,8 @@ class DomMethodCallExpr extends MethodCallExpr {
|
||||
name = "setAttributeNS" and argPos = 2
|
||||
) and
|
||||
// restrict to potentially dangerous attributes
|
||||
exists(string attr |
|
||||
attr = "action" or attr = "formaction" or attr = "href" or attr = "src" |
|
||||
getArgument(argPos-1).getStringValue().toLowerCase() = attr
|
||||
exists(string attr | attr = "action" or attr = "formaction" or attr = "href" or attr = "src" |
|
||||
getArgument(argPos - 1).getStringValue().toLowerCase() = attr
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ module DifferentKindsComparisonBypass {
|
||||
*/
|
||||
class DifferentKindsComparison extends Comparison {
|
||||
Source lSource;
|
||||
|
||||
Source rSource;
|
||||
|
||||
DifferentKindsComparison() {
|
||||
|
||||
@@ -29,9 +29,7 @@ module HardcodedCredentials {
|
||||
class ConstantStringSource extends Source, DataFlow::ValueNode {
|
||||
override ConstantString astNode;
|
||||
|
||||
ConstantStringSource() {
|
||||
not astNode.getStringValue() = ""
|
||||
}
|
||||
ConstantStringSource() { not astNode.getStringValue() = "" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user