mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Merge remote-tracking branch 'upstream/main' into incomplete-hostname
This commit is contained in:
@@ -8,6 +8,6 @@
|
||||
|
||||
import javascript
|
||||
|
||||
from JSXAttribute a
|
||||
from JsxAttribute a
|
||||
where a.getName() = "dangerouslySetInnerHTML"
|
||||
select a
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Configures boosting for adaptive threat modeling (ATM).
|
||||
*/
|
||||
|
||||
private import javascript as raw
|
||||
private import javascript as JS
|
||||
import EndpointTypes
|
||||
|
||||
/**
|
||||
@@ -28,23 +28,23 @@ import EndpointTypes
|
||||
* `isAdditionalFlowStep` with a more generalised definition of additional edges. See
|
||||
* `NosqlInjectionATM.qll` for an example of doing this.
|
||||
*/
|
||||
abstract class ATMConfig extends string {
|
||||
abstract class AtmConfig extends string {
|
||||
bindingset[this]
|
||||
ATMConfig() { any() }
|
||||
AtmConfig() { any() }
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
*
|
||||
* Holds if `source` is a known source of flow.
|
||||
*/
|
||||
predicate isKnownSource(raw::DataFlow::Node source) { none() }
|
||||
predicate isKnownSource(JS::DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
*
|
||||
* Holds if `sink` is a known sink of flow.
|
||||
*/
|
||||
predicate isKnownSink(raw::DataFlow::Node sink) { none() }
|
||||
predicate isKnownSink(JS::DataFlow::Node sink) { none() }
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
@@ -52,7 +52,7 @@ abstract class ATMConfig extends string {
|
||||
* Holds if the candidate source `candidateSource` predicted by the machine learning model should be
|
||||
* an effective source, i.e. one considered as a possible source of flow in the boosted query.
|
||||
*/
|
||||
predicate isEffectiveSource(raw::DataFlow::Node candidateSource) { none() }
|
||||
predicate isEffectiveSource(JS::DataFlow::Node candidateSource) { none() }
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
@@ -60,29 +60,7 @@ abstract class ATMConfig extends string {
|
||||
* Holds if the candidate sink `candidateSink` predicted by the machine learning model should be
|
||||
* an effective sink, i.e. one considered as a possible sink of flow in the boosted query.
|
||||
*/
|
||||
predicate isEffectiveSink(raw::DataFlow::Node candidateSink) { none() }
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
*
|
||||
* Holds if the candidate sink `candidateSink` predicted by the machine learning model should be
|
||||
* an effective sink that overrides the score provided by the machine learning model with the
|
||||
* score `score` for reason `why`. The effective sinks identified by this predicate MUST be a
|
||||
* subset of those identified by the `isEffectiveSink` predicate.
|
||||
*
|
||||
* For example, in the ATM external API query, we use this method to ensure the ATM external API
|
||||
* query produces the same results as the standard external API query, but assigns flows
|
||||
* involving sinks that are filtered out by the endpoint filters a score of 0.
|
||||
*
|
||||
* This predicate can be phased out once we no longer need to rely on predicates like
|
||||
* `paddedScore` in the ATM CodeQL libraries to add scores to alert messages in a way that works
|
||||
* with lexical sort orders.
|
||||
*/
|
||||
predicate isEffectiveSinkWithOverridingScore(
|
||||
raw::DataFlow::Node candidateSink, float score, string why
|
||||
) {
|
||||
none()
|
||||
}
|
||||
predicate isEffectiveSink(JS::DataFlow::Node candidateSink) { none() }
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL. This API may change in the future.
|
||||
@@ -110,3 +88,6 @@ abstract class ATMConfig extends string {
|
||||
*/
|
||||
float getScoreCutoff() { result = 0.0 }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AtmConfig */
|
||||
deprecated class ATMConfig = AtmConfig;
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
* Provides information about the results of boosted queries for use in adaptive threat modeling (ATM).
|
||||
*/
|
||||
|
||||
private import javascript as raw
|
||||
private import raw::DataFlow as DataFlow
|
||||
private import javascript::DataFlow as DataFlow
|
||||
import ATMConfig
|
||||
private import BaseScoring
|
||||
private import EndpointScoring as EndpointScoring
|
||||
|
||||
@@ -12,7 +12,7 @@ external predicate availableMlModels(
|
||||
);
|
||||
|
||||
/** Get the ATM configuration. */
|
||||
ATMConfig getCfg() { any() }
|
||||
AtmConfig getCfg() { any() }
|
||||
|
||||
/**
|
||||
* A string containing scoring information produced by a scoring model.
|
||||
|
||||
@@ -61,7 +61,7 @@ predicate isArgumentToKnownLibrarySinkFunction(DataFlow::Node n) {
|
||||
* This corresponds to known sinks from security queries whose sources include remote flow and
|
||||
* DOM-based sources.
|
||||
*/
|
||||
predicate isKnownExternalAPIQuerySink(DataFlow::Node n) {
|
||||
predicate isKnownExternalApiQuerySink(DataFlow::Node n) {
|
||||
n instanceof Xxe::Sink or
|
||||
n instanceof TaintedPath::Sink or
|
||||
n instanceof XpathInjection::Sink or
|
||||
@@ -86,11 +86,14 @@ predicate isKnownExternalAPIQuerySink(DataFlow::Node n) {
|
||||
n instanceof HttpToFileAccess::Sink
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for isKnownExternalApiQuerySink */
|
||||
deprecated predicate isKnownExternalAPIQuerySink = isKnownExternalApiQuerySink/1;
|
||||
|
||||
/**
|
||||
* Holds if the node `n` is a known sink in a modeled library.
|
||||
*/
|
||||
predicate isKnownLibrarySink(DataFlow::Node n) {
|
||||
isKnownExternalAPIQuerySink(n) or
|
||||
isKnownExternalApiQuerySink(n) or
|
||||
n instanceof CleartextLogging::Sink or
|
||||
n instanceof StackTraceExposure::Sink or
|
||||
n instanceof ShellCommandInjectionFromEnvironment::Sink or
|
||||
@@ -207,7 +210,7 @@ predicate isOtherModeledArgument(DataFlow::Node n, FilteringReason reason) {
|
||||
DatabaseAccess and
|
||||
reason instanceof DatabaseAccessReason
|
||||
or
|
||||
call = DOM::domValueRef() and reason instanceof DOMReason
|
||||
call = DOM::domValueRef() and reason instanceof DomReason
|
||||
or
|
||||
call.getCalleeName() = "next" and
|
||||
exists(DataFlow::FunctionNode f | call = f.getLastParameter().getACall()) and
|
||||
|
||||
@@ -62,14 +62,11 @@ private float getScoreForSource(DataFlow::Node source) {
|
||||
private float getScoreForSink(DataFlow::Node sink) {
|
||||
if getCfg().isKnownSink(sink)
|
||||
then result = 1.0
|
||||
else
|
||||
if getCfg().isEffectiveSinkWithOverridingScore(sink, result, _)
|
||||
then any()
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), result)
|
||||
)
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), result)
|
||||
)
|
||||
}
|
||||
|
||||
class EndpointScoringResults extends ScoringResults {
|
||||
@@ -109,10 +106,6 @@ class EndpointScoringResults extends ScoringResults {
|
||||
result = "known" and getCfg().isKnownSink(sink)
|
||||
or
|
||||
not getCfg().isKnownSink(sink) and
|
||||
getCfg().isEffectiveSinkWithOverridingScore(sink, _, result)
|
||||
or
|
||||
not getCfg().isKnownSink(sink) and
|
||||
not getCfg().isEffectiveSinkWithOverridingScore(sink, _, _) and
|
||||
result =
|
||||
"predicted (scores: " +
|
||||
concat(EndpointType type, float score |
|
||||
@@ -127,29 +120,21 @@ class EndpointScoringResults extends ScoringResults {
|
||||
override predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) {
|
||||
if getCfg().isKnownSink(sink)
|
||||
then any()
|
||||
else
|
||||
if getCfg().isEffectiveSinkWithOverridingScore(sink, _, _)
|
||||
then
|
||||
exists(float score |
|
||||
getCfg().isEffectiveSinkWithOverridingScore(sink, score, _) and
|
||||
score >= getCfg().getScoreCutoff()
|
||||
)
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
exists(float sinkScore |
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(),
|
||||
sinkScore) and
|
||||
// Include the endpoint if (a) the query endpoint type scores higher than all other
|
||||
// endpoint types, or (b) the query endpoint type scores at least
|
||||
// 0.5 - (getCfg().getScoreCutoff() / 2).
|
||||
sinkScore >=
|
||||
[
|
||||
max(float s | ModelScoring::endpointScores(sink, _, s)),
|
||||
0.5 - getCfg().getScoreCutoff() / 2
|
||||
]
|
||||
)
|
||||
else (
|
||||
// This restriction on `sink` has no semantic effect but improves performance.
|
||||
getCfg().isEffectiveSink(sink) and
|
||||
exists(float sinkScore |
|
||||
ModelScoring::endpointScores(sink, getCfg().getASinkEndpointType().getEncoding(), sinkScore) and
|
||||
// Include the endpoint if (a) the query endpoint type scores higher than all other
|
||||
// endpoint types, or (b) the query endpoint type scores at least
|
||||
// 0.5 - (getCfg().getScoreCutoff() / 2).
|
||||
sinkScore >=
|
||||
[
|
||||
max(float s | ModelScoring::endpointScores(sink, _, s)),
|
||||
0.5 - getCfg().getScoreCutoff() / 2
|
||||
]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ newtype TFilteringReason =
|
||||
TMembershipCandidateTestReason() or
|
||||
TFileSystemAccessReason() or
|
||||
TDatabaseAccessReason() or
|
||||
TDOMReason() or
|
||||
TDomReason() or
|
||||
TNextFunctionCallReason() or
|
||||
TArgumentToArrayReason() or
|
||||
TArgumentToBuiltinGlobalVarRefReason() or
|
||||
@@ -161,12 +161,15 @@ class DatabaseAccessReason extends NotASinkReason, TDatabaseAccessReason {
|
||||
override int getEncoding() { result = 21 }
|
||||
}
|
||||
|
||||
class DOMReason extends NotASinkReason, TDOMReason {
|
||||
class DomReason extends NotASinkReason, TDomReason {
|
||||
override string getDescription() { result = "DOM" }
|
||||
|
||||
override int getEncoding() { result = 22 }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DomReason */
|
||||
deprecated class DOMReason = DomReason;
|
||||
|
||||
class NextFunctionCallReason extends NotASinkReason, TNextFunctionCallReason {
|
||||
override string getDescription() { result = "NextFunctionCall" }
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ private import FeaturizationConfig
|
||||
/**
|
||||
* Gets a tokenized representation of the AST node for use in the `enclosingFunctionBody` feature.
|
||||
*/
|
||||
string getTokenizedAstNode(ASTNode node) {
|
||||
string getTokenizedAstNode(AstNode node) {
|
||||
// e.g. `x` -> "x"
|
||||
result = node.(Identifier).getName()
|
||||
or
|
||||
@@ -35,12 +35,15 @@ string getTokenizedAstNode(ASTNode node) {
|
||||
|
||||
/** Gets an AST node within the function `f` that we should featurize. */
|
||||
pragma[inline]
|
||||
ASTNode getAnASTNodeToFeaturize(Function f) {
|
||||
AstNode getAnAstNodeToFeaturize(Function f) {
|
||||
result.getParent*() = f and
|
||||
// Don't featurize the function name as part of the function body tokens
|
||||
not result = f.getIdentifier()
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getAnAstNodeToFeaturize */
|
||||
deprecated ASTNode getAnASTNodeToFeaturize(Function f) { result = getAnAstNodeToFeaturize(f) }
|
||||
|
||||
/**
|
||||
* Gets a function that contains the endpoint.
|
||||
*
|
||||
@@ -72,7 +75,7 @@ private int getMaxNumAstNodes() { result = 1024 }
|
||||
private int getNumAstNodesInFunction(Function function) {
|
||||
// Restrict the values `function` can take on
|
||||
function = getAFunctionForEndpoint(_) and
|
||||
result = count(getAnASTNodeToFeaturize(function))
|
||||
result = count(getAnAstNodeToFeaturize(function))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,16 +124,19 @@ Function getRepresentativeFunctionForEndpoint(DataFlow::Node endpoint) {
|
||||
}
|
||||
|
||||
/** Returns an AST node within the function `f` that an associated token feature. */
|
||||
ASTNode getAnASTNodeWithAFeature(Function f) {
|
||||
AstNode getAnAstNodeWithAFeature(Function f) {
|
||||
// Performance optimization: Restrict the set of functions to those containing an endpoint to featurize.
|
||||
f = getRepresentativeFunctionForEndpoint(any(FeaturizationConfig cfg).getAnEndpointToFeaturize()) and
|
||||
result = getAnASTNodeToFeaturize(f)
|
||||
result = getAnAstNodeToFeaturize(f)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getAnAstNodeWithAFeature */
|
||||
deprecated ASTNode getAnASTNodeWithAFeature(Function f) { result = getAnAstNodeWithAFeature(f) }
|
||||
|
||||
/** Returns the number of source-code characters in a function. */
|
||||
int getNumCharsInFunction(Function f) {
|
||||
result =
|
||||
strictsum(ASTNode node | node = getAnASTNodeWithAFeature(f) | getTokenizedAstNode(node).length())
|
||||
strictsum(AstNode node | node = getAnAstNodeWithAFeature(f) | getTokenizedAstNode(node).length())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,8 +155,8 @@ string getBodyTokensFeature(Function function) {
|
||||
// large body features are replaced by the absent token.
|
||||
//
|
||||
// We count nodes instead of tokens because tokens are often not unique.
|
||||
strictcount(ASTNode node |
|
||||
node = getAnASTNodeToFeaturize(function) and
|
||||
strictcount(AstNode node |
|
||||
node = getAnAstNodeToFeaturize(function) and
|
||||
exists(getTokenizedAstNode(node))
|
||||
) <= 256 and
|
||||
// Performance optimization: If a function has more than getMaxChars() characters in its body subtokens,
|
||||
@@ -161,8 +167,8 @@ string getBodyTokensFeature(Function function) {
|
||||
// The use of a nested exists here allows us to avoid duplicates due to two AST nodes in the
|
||||
// same location featurizing to the same token. By using a nested exists, we take only unique
|
||||
// (location, token) pairs.
|
||||
exists(ASTNode node |
|
||||
node = getAnASTNodeToFeaturize(function) and
|
||||
exists(AstNode node |
|
||||
node = getAnAstNodeToFeaturize(function) and
|
||||
token = getTokenizedAstNode(node) and
|
||||
l = node.getLocation()
|
||||
)
|
||||
|
||||
@@ -87,8 +87,8 @@ module SinkEndpointFilter {
|
||||
}
|
||||
}
|
||||
|
||||
class NosqlInjectionATMConfig extends ATMConfig {
|
||||
NosqlInjectionATMConfig() { this = "NosqlInjectionATMConfig" }
|
||||
class NosqlInjectionAtmConfig extends AtmConfig {
|
||||
NosqlInjectionAtmConfig() { this = "NosqlInjectionATMConfig" }
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) {
|
||||
source instanceof NosqlInjection::Source or TaintedObject::isSource(source, _)
|
||||
@@ -103,7 +103,10 @@ class NosqlInjectionATMConfig extends ATMConfig {
|
||||
override EndpointType getASinkEndpointType() { result instanceof NosqlInjectionSinkType }
|
||||
}
|
||||
|
||||
/** Holds if src -> trg is an additional flow step in the non-boosted NoSQL injection security query. */
|
||||
/** DEPRECATED: Alias for NosqlInjectionAtmConfig */
|
||||
deprecated class NosqlInjectionATMConfig = NosqlInjectionAtmConfig;
|
||||
|
||||
/** Holds if src -> trg is an additional flow step in the non-boosted NoSql injection security query. */
|
||||
predicate isBaseAdditionalFlowStep(
|
||||
DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl
|
||||
) {
|
||||
@@ -112,7 +115,7 @@ predicate isBaseAdditionalFlowStep(
|
||||
// additional flow step to track taint through NoSQL query objects
|
||||
inlbl = TaintedObject::label() and
|
||||
outlbl = TaintedObject::label() and
|
||||
exists(NoSQL::Query query, DataFlow::SourceNode queryObj |
|
||||
exists(NoSql::Query query, DataFlow::SourceNode queryObj |
|
||||
queryObj.flowsToExpr(query) and
|
||||
queryObj.flowsTo(trg) and
|
||||
src = queryObj.getAPropertyWrite().getRhs()
|
||||
@@ -120,13 +123,17 @@ predicate isBaseAdditionalFlowStep(
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value that is (transitively) written to `query`, where `query` is a NoSQL sink.
|
||||
*
|
||||
* This predicate allows us to propagate data flow through property writes and array constructors
|
||||
* within a query object, enabling the security query to pick up NoSQL injection vulnerabilities
|
||||
* involving more complex queries.
|
||||
*/
|
||||
DataFlow::Node getASubexpressionWithinQuery(DataFlow::Node query) {
|
||||
any(NosqlInjectionAtmConfig cfg).isEffectiveSink(query) and
|
||||
exists(DataFlow::SourceNode receiver |
|
||||
receiver.flowsTo(getASubexpressionWithinQuery*(query.getALocalSource())) and
|
||||
receiver = [getASubexpressionWithinQuery(query), query].getALocalSource()
|
||||
|
|
||||
result =
|
||||
[receiver.getAPropertyWrite().getRhs(), receiver.(DataFlow::ArrayCreationNode).getAnElement()]
|
||||
)
|
||||
@@ -152,7 +159,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
sink.(NosqlInjection::Sink).getAFlowLabel() = label
|
||||
or
|
||||
// Allow effective sinks to have any taint label
|
||||
any(NosqlInjectionATMConfig cfg).isEffectiveSink(sink)
|
||||
any(NosqlInjectionAtmConfig cfg).isEffectiveSink(sink)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
@@ -171,7 +178,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
isBaseAdditionalFlowStep(src, trg, inlbl, outlbl)
|
||||
or
|
||||
// relaxed version of previous step to track taint through unmodeled NoSQL query objects
|
||||
any(NosqlInjectionATMConfig cfg).isEffectiveSink(trg) and
|
||||
any(NosqlInjectionAtmConfig cfg).isEffectiveSink(trg) and
|
||||
src = getASubexpressionWithinQuery(trg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ module SinkEndpointFilter {
|
||||
}
|
||||
}
|
||||
|
||||
class SqlInjectionATMConfig extends ATMConfig {
|
||||
SqlInjectionATMConfig() { this = "SqlInjectionATMConfig" }
|
||||
class SqlInjectionAtmConfig extends AtmConfig {
|
||||
SqlInjectionAtmConfig() { this = "SqlInjectionATMConfig" }
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof SqlInjection::Source }
|
||||
|
||||
@@ -74,6 +74,9 @@ class SqlInjectionATMConfig extends ATMConfig {
|
||||
override EndpointType getASinkEndpointType() { result instanceof SqlInjectionSinkType }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SqlInjectionAtmConfig */
|
||||
deprecated class SqlInjectionATMConfig = SqlInjectionAtmConfig;
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about SQL injection vulnerabilities.
|
||||
*
|
||||
@@ -86,7 +89,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof SqlInjection::Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof SqlInjection::Sink or any(SqlInjectionATMConfig cfg).isEffectiveSink(sink)
|
||||
sink instanceof SqlInjection::Sink or any(SqlInjectionAtmConfig cfg).isEffectiveSink(sink)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
|
||||
@@ -59,8 +59,8 @@ module SinkEndpointFilter {
|
||||
}
|
||||
}
|
||||
|
||||
class TaintedPathATMConfig extends ATMConfig {
|
||||
TaintedPathATMConfig() { this = "TaintedPathATMConfig" }
|
||||
class TaintedPathAtmConfig extends AtmConfig {
|
||||
TaintedPathAtmConfig() { this = "TaintedPathATMConfig" }
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof TaintedPath::Source }
|
||||
|
||||
@@ -73,6 +73,9 @@ class TaintedPathATMConfig extends ATMConfig {
|
||||
override EndpointType getASinkEndpointType() { result instanceof TaintedPathSinkType }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for TaintedPathAtmConfig */
|
||||
deprecated class TaintedPathATMConfig = TaintedPathAtmConfig;
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about path injection vulnerabilities.
|
||||
*
|
||||
@@ -88,7 +91,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
label = sink.(TaintedPath::Sink).getAFlowLabel()
|
||||
or
|
||||
// Allow effective sinks to have any taint label
|
||||
any(TaintedPathATMConfig cfg).isEffectiveSink(sink)
|
||||
any(TaintedPathAtmConfig cfg).isEffectiveSink(sink)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof TaintedPath::Sanitizer }
|
||||
|
||||
@@ -60,8 +60,8 @@ module SinkEndpointFilter {
|
||||
}
|
||||
}
|
||||
|
||||
class DomBasedXssATMConfig extends ATMConfig {
|
||||
DomBasedXssATMConfig() { this = "DomBasedXssATMConfig" }
|
||||
class DomBasedXssAtmConfig extends AtmConfig {
|
||||
DomBasedXssAtmConfig() { this = "DomBasedXssATMConfig" }
|
||||
|
||||
override predicate isKnownSource(DataFlow::Node source) { source instanceof DomBasedXss::Source }
|
||||
|
||||
@@ -74,6 +74,9 @@ class DomBasedXssATMConfig extends ATMConfig {
|
||||
override EndpointType getASinkEndpointType() { result instanceof XssSinkType }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DomBasedXssAtmConfig */
|
||||
deprecated class DomBasedXssATMConfig = DomBasedXssAtmConfig;
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about XSS vulnerabilities.
|
||||
*
|
||||
@@ -87,7 +90,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof DomBasedXss::Sink or
|
||||
any(DomBasedXssATMConfig cfg).isEffectiveSink(sink)
|
||||
any(DomBasedXssAtmConfig cfg).isEffectiveSink(sink)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-experimental-atm-lib
|
||||
version: 0.0.6
|
||||
version: 0.1.1
|
||||
extractor: javascript
|
||||
library: true
|
||||
groups:
|
||||
|
||||
@@ -33,7 +33,7 @@ string getDescriptionForAlertCandidate(
|
||||
) {
|
||||
result = "excluded[reason=" + getAReasonSinkExcluded(sinkCandidate, query) + "]"
|
||||
or
|
||||
getATMCfg(query).isKnownSink(sinkCandidate) and
|
||||
getAtmCfg(query).isKnownSink(sinkCandidate) and
|
||||
result = "excluded[reason=known-sink]"
|
||||
or
|
||||
not exists(getAReasonSinkExcluded(sinkCandidate, query)) and
|
||||
|
||||
@@ -20,7 +20,7 @@ import semmle.javascript.security.dataflow.DeepObjectResourceExhaustionQuery as
|
||||
import semmle.javascript.security.dataflow.DifferentKindsComparisonBypassQuery as DifferentKindsComparisonBypass
|
||||
import semmle.javascript.security.dataflow.DomBasedXssQuery as DomBasedXss
|
||||
import semmle.javascript.security.dataflow.ExceptionXssQuery as ExceptionXss
|
||||
import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedDataQuery as ExternalAPIUsedWithUntrustedData
|
||||
import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedDataQuery as ExternalApiUsedWithUntrustedData
|
||||
import semmle.javascript.security.dataflow.FileAccessToHttpQuery as FileAccessToHttp
|
||||
import semmle.javascript.security.dataflow.HardcodedCredentialsQuery as HardcodedCredentials
|
||||
import semmle.javascript.security.dataflow.HardcodedDataInterpretedAsCodeQuery as HardcodedDataInterpretedAsCode
|
||||
|
||||
@@ -23,17 +23,20 @@ import NoFeaturizationRestrictionsConfig
|
||||
import Queries
|
||||
|
||||
/** Gets the ATM configuration object for the specified query. */
|
||||
ATMConfig getATMCfg(Query query) {
|
||||
AtmConfig getAtmCfg(Query query) {
|
||||
query instanceof NosqlInjectionQuery and
|
||||
result instanceof NosqlInjectionATM::NosqlInjectionATMConfig
|
||||
result instanceof NosqlInjectionATM::NosqlInjectionAtmConfig
|
||||
or
|
||||
query instanceof SqlInjectionQuery and result instanceof SqlInjectionATM::SqlInjectionATMConfig
|
||||
query instanceof SqlInjectionQuery and result instanceof SqlInjectionATM::SqlInjectionAtmConfig
|
||||
or
|
||||
query instanceof TaintedPathQuery and result instanceof TaintedPathATM::TaintedPathATMConfig
|
||||
query instanceof TaintedPathQuery and result instanceof TaintedPathATM::TaintedPathAtmConfig
|
||||
or
|
||||
query instanceof XssQuery and result instanceof XssATM::DomBasedXssATMConfig
|
||||
query instanceof XssQuery and result instanceof XssATM::DomBasedXssAtmConfig
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getAtmCfg */
|
||||
deprecated ATMConfig getATMCfg(Query query) { result = getAtmCfg(query) }
|
||||
|
||||
/** Gets the ATM data flow configuration for the specified query. */
|
||||
DataFlow::Configuration getDataFlowCfg(Query query) {
|
||||
query instanceof NosqlInjectionQuery and result instanceof NosqlInjectionATM::Configuration
|
||||
@@ -47,7 +50,7 @@ DataFlow::Configuration getDataFlowCfg(Query query) {
|
||||
|
||||
/** Gets a known sink for the specified query. */
|
||||
private DataFlow::Node getASink(Query query) {
|
||||
getATMCfg(query).isKnownSink(result) and
|
||||
getAtmCfg(query).isKnownSink(result) and
|
||||
// Only consider the source code for the project being analyzed.
|
||||
exists(result.getFile().getRelativePath())
|
||||
}
|
||||
@@ -71,10 +74,7 @@ private DataFlow::Node getANotASink(NotASinkReason reason) {
|
||||
* specified query.
|
||||
*/
|
||||
private DataFlow::Node getAnUnknown(Query query) {
|
||||
(
|
||||
getATMCfg(query).isEffectiveSink(result) or
|
||||
getATMCfg(query).isEffectiveSinkWithOverridingScore(result, _, _)
|
||||
) and
|
||||
getAtmCfg(query).isEffectiveSink(result) and
|
||||
not result = getASink(query) and
|
||||
// Only consider the source code for the project being analyzed.
|
||||
exists(result.getFile().getRelativePath())
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* For internal use only.
|
||||
*
|
||||
* Maps ML-powered queries to their `EndpointType` for clearer labelling while evaluating ML model during training.
|
||||
*/
|
||||
|
||||
import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionATM
|
||||
import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionATM
|
||||
import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathATM
|
||||
import experimental.adaptivethreatmodeling.XssATM as XssATM
|
||||
import experimental.adaptivethreatmodeling.AdaptiveThreatModeling
|
||||
|
||||
from string queryName, AtmConfig c, EndpointType e
|
||||
where
|
||||
(
|
||||
queryName = "SqlInjectionATM.ql" and
|
||||
c instanceof SqlInjectionATM::SqlInjectionAtmConfig
|
||||
or
|
||||
queryName = "NosqlInjectionATM.ql" and
|
||||
c instanceof NosqlInjectionATM::NosqlInjectionAtmConfig
|
||||
or
|
||||
queryName = "TaintedPathInjectionATM.ql" and
|
||||
c instanceof TaintedPathATM::TaintedPathAtmConfig
|
||||
or
|
||||
queryName = "XssATM.ql" and c instanceof XssATM::DomBasedXssAtmConfig
|
||||
) and
|
||||
e = c.getASinkEndpointType()
|
||||
select queryName, e.getEncoding() as endpointTypeEncoded
|
||||
@@ -19,8 +19,8 @@ EndpointType getEndpointType() { result instanceof NosqlInjectionSinkType }
|
||||
DataFlow::Node getAPositiveEndpoint() { result instanceof NosqlInjection::Sink }
|
||||
|
||||
/** An ATM configuration to find misclassified endpoints of type `getEndpointType()`. */
|
||||
class ExtractMisclassifiedEndpointsATMConfig extends ATMConfig {
|
||||
ExtractMisclassifiedEndpointsATMConfig() { this = "ExtractMisclassifiedEndpointsATMConfig" }
|
||||
class ExtractMisclassifiedEndpointsAtmConfig extends AtmConfig {
|
||||
ExtractMisclassifiedEndpointsAtmConfig() { this = "ExtractMisclassifiedEndpointsATMConfig" }
|
||||
|
||||
override predicate isEffectiveSink(DataFlow::Node sinkCandidate) {
|
||||
sinkCandidate = getAPositiveEndpoint()
|
||||
@@ -31,7 +31,7 @@ class ExtractMisclassifiedEndpointsATMConfig extends ATMConfig {
|
||||
|
||||
/** Get an endpoint from `getAPositiveEndpoint()` that is incorrectly excluded from the results. */
|
||||
DataFlow::Node getAMisclassifedEndpoint() {
|
||||
any(ExtractMisclassifiedEndpointsATMConfig config).isEffectiveSink(result) and
|
||||
any(ExtractMisclassifiedEndpointsAtmConfig config).isEffectiveSink(result) and
|
||||
not any(ScoringResults results).shouldResultBeIncluded(_, result)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: codeql/javascript-experimental-atm-queries
|
||||
language: javascript
|
||||
version: 0.0.6
|
||||
version: 0.1.1
|
||||
suites: codeql-suites
|
||||
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
|
||||
groups:
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
## 0.0.12
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Added support for TypeScript 4.6.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added sources from the [`jszip`](https://www.npmjs.com/package/jszip) library to the `js/zipslip` query.
|
||||
|
||||
## 0.0.11
|
||||
|
||||
## 0.0.10
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
|
||||
import semmle.javascript.Externs
|
||||
|
||||
/** Holds if `et` is a root interface of the DOM type hierarchy. */
|
||||
predicate isDOMRootType(ExternalType et) {
|
||||
exists(string n | n = et.getName() | n = "EventTarget" or n = "StyleSheet")
|
||||
}
|
||||
/** DEPRECATED: Alias for isDomRootType */
|
||||
deprecated predicate isDOMRootType = isDomRootType/1;
|
||||
|
||||
/** Holds if `p` is declared as a property of a DOM class or interface. */
|
||||
pragma[nomagic]
|
||||
predicate isDOMProperty(string p) {
|
||||
predicate isDomProperty(string p) {
|
||||
exists(ExternalMemberDecl emd | emd.getName() = p |
|
||||
isDOMRootType(emd.getDeclaringType().getASupertype*())
|
||||
isDomRootType(emd.getDeclaringType().getASupertype*())
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for isDomProperty */
|
||||
deprecated predicate isDOMProperty = isDomProperty/1;
|
||||
|
||||
@@ -143,7 +143,7 @@ predicate hasNoEffect(Expr e) {
|
||||
// don't complain about declarations
|
||||
not isDeclaration(e) and
|
||||
// exclude DOM properties, which sometimes have magical auto-update properties
|
||||
not isDOMProperty(e.(PropAccess).getPropertyName()) and
|
||||
not isDomProperty(e.(PropAccess).getPropertyName()) and
|
||||
// exclude xUnit.js annotations
|
||||
not e instanceof XUnitAnnotation and
|
||||
// exclude common patterns that are most likely intentional
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added sources from the [`jszip`](https://www.npmjs.com/package/jszip) library to the `js/zipslip` query.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Some modules that started with a lowercase letter have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Some predicates from `DefUse.qll`, `DataFlow.qll`, `TaintTracking.qll`, `DOM.qll`, `Definitions.qll` that weren't used by any query have been deprecated.
|
||||
The documentation for each predicate points to an alternative.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added support for TypeScript 4.6.
|
||||
9
javascript/ql/lib/change-notes/released/0.0.12.md
Normal file
9
javascript/ql/lib/change-notes/released/0.0.12.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 0.0.12
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Added support for TypeScript 4.6.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added sources from the [`jszip`](https://www.npmjs.com/package/jszip) library to the `js/zipslip` query.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.11
|
||||
lastReleaseVersion: 0.0.12
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-all
|
||||
version: 0.0.12-dev
|
||||
version: 0.0.13-dev
|
||||
groups: javascript
|
||||
dbscheme: semmlecode.javascript.dbscheme
|
||||
extractor: javascript
|
||||
|
||||
@@ -185,11 +185,6 @@ class AmdModuleDefinition extends CallExpr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AmdModuleDefinition` instead.
|
||||
*/
|
||||
deprecated class AMDModuleDefinition = AmdModuleDefinition;
|
||||
|
||||
/** An AMD dependency, considered as a path expression. */
|
||||
private class AmdDependencyPath extends PathExprCandidate {
|
||||
AmdDependencyPath() {
|
||||
@@ -327,8 +322,3 @@ class AmdModule extends Module {
|
||||
result = getDefine().getModuleExpr().flow()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AmdModule` instead.
|
||||
*/
|
||||
deprecated class AMDModule = AmdModule;
|
||||
|
||||
@@ -22,7 +22,7 @@ private import semmle.javascript.internal.CachedStages
|
||||
* abs(-42);
|
||||
* ```
|
||||
*/
|
||||
class ASTNode extends @ast_node, NodeInStmtContainer {
|
||||
class AstNode extends @ast_node, NodeInStmtContainer {
|
||||
override Location getLocation() { hasLocation(this, result) }
|
||||
|
||||
override File getFile() {
|
||||
@@ -84,7 +84,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
|
||||
* _Note_: The indices of child nodes are considered an implementation detail and may
|
||||
* change between versions of the extractor.
|
||||
*/
|
||||
ASTNode getChild(int i) {
|
||||
AstNode getChild(int i) {
|
||||
result = this.getChildExpr(i) or
|
||||
result = this.getChildStmt(i) or
|
||||
properties(result, this, i, _, _) or
|
||||
@@ -101,7 +101,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
|
||||
TypeExpr getChildTypeExpr(int i) { typeexprs(result, _, this, i, _) }
|
||||
|
||||
/** Gets a child node of this node. */
|
||||
ASTNode getAChild() { result = this.getChild(_) }
|
||||
AstNode getAChild() { result = this.getChild(_) }
|
||||
|
||||
/** Gets a child expression of this node. */
|
||||
Expr getAChildExpr() { result = this.getChildExpr(_) }
|
||||
@@ -120,7 +120,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
|
||||
|
||||
/** Gets the parent node of this node, if any. */
|
||||
cached
|
||||
ASTNode getParent() { Stages::Ast::ref() and this = result.getAChild() }
|
||||
AstNode getParent() { Stages::Ast::ref() and this = result.getAChild() }
|
||||
|
||||
/** Gets the first control flow node belonging to this syntactic entity. */
|
||||
ControlFlowNode getFirstControlFlowNode() { result = this }
|
||||
@@ -184,6 +184,9 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AstNode */
|
||||
deprecated class ASTNode = AstNode;
|
||||
|
||||
/**
|
||||
* Holds if the given file is a `.d.ts` file.
|
||||
*/
|
||||
@@ -334,7 +337,10 @@ class EventHandlerCode extends @event_handler, CodeInAttribute { }
|
||||
* <a href="javascript:alert('hi')">Click me</a>
|
||||
* ```
|
||||
*/
|
||||
class JavaScriptURL extends @javascript_url, CodeInAttribute { }
|
||||
class JavaScriptUrl extends @javascript_url, CodeInAttribute { }
|
||||
|
||||
/** DEPRECATED: Alias for JavaScriptUrl */
|
||||
deprecated class JavaScriptURL = JavaScriptUrl;
|
||||
|
||||
/**
|
||||
* A toplevel syntactic entity containing Closure-style externs definitions.
|
||||
@@ -361,7 +367,7 @@ class Externs extends TopLevel {
|
||||
* i = 9
|
||||
* ```
|
||||
*/
|
||||
class ExprOrStmt extends @expr_or_stmt, ControlFlowNode, ASTNode { }
|
||||
class ExprOrStmt extends @expr_or_stmt, ControlFlowNode, AstNode { }
|
||||
|
||||
/**
|
||||
* A program element that contains statements, but isn't itself
|
||||
@@ -375,7 +381,7 @@ class ExprOrStmt extends @expr_or_stmt, ControlFlowNode, ASTNode { }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class StmtContainer extends @stmt_container, ASTNode {
|
||||
class StmtContainer extends @stmt_container, AstNode {
|
||||
/** Gets the innermost enclosing container in which this container is nested. */
|
||||
cached
|
||||
StmtContainer getEnclosingContainer() { none() }
|
||||
@@ -405,7 +411,7 @@ class StmtContainer extends @stmt_container, ASTNode {
|
||||
* For scripts or modules, this is the container itself; for functions,
|
||||
* it is the function body.
|
||||
*/
|
||||
ASTNode getBody() { result = this }
|
||||
AstNode getBody() { result = this }
|
||||
|
||||
/**
|
||||
* Gets the (unique) entry node of the control flow graph for this toplevel or function.
|
||||
@@ -470,7 +476,7 @@ module AST {
|
||||
* function id(x) { return x; } // function declaration
|
||||
* ```
|
||||
*/
|
||||
class ValueNode extends ASTNode, @dataflownode {
|
||||
class ValueNode extends AstNode, @dataflownode {
|
||||
/** Gets type inference results for this element. */
|
||||
DataFlow::AnalyzedNode analyze() { result = DataFlow::valueNode(this).analyze() }
|
||||
|
||||
|
||||
@@ -13,11 +13,6 @@ class ArrayAccess = IndexExpr;
|
||||
|
||||
class AssignOp = CompoundAssignExpr;
|
||||
|
||||
/**
|
||||
* DEPRECATED: The name `BlockStmt` is now preferred in all languages.
|
||||
*/
|
||||
deprecated class Block = BlockStmt;
|
||||
|
||||
class BoolLiteral = BooleanLiteral;
|
||||
|
||||
class CaseStmt = Case;
|
||||
@@ -67,302 +62,3 @@ class ThisAccess = ThisExpr;
|
||||
class VariableAccess = VarAccess;
|
||||
|
||||
class XorBitwiseExpr = XOrExpr;
|
||||
|
||||
// Aliases for deprecated predicates from the dbscheme
|
||||
/**
|
||||
* Alias for the predicate `is_externs` defined in the .dbscheme.
|
||||
* Use `TopLevel#isExterns()` instead.
|
||||
*/
|
||||
deprecated predicate isExterns(TopLevel toplevel) { is_externs(toplevel) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_module` defined in the .dbscheme.
|
||||
* Use the `Module` class in `Module.qll` instead.
|
||||
*/
|
||||
deprecated predicate isModule(TopLevel toplevel) { is_module(toplevel) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_nodejs` defined in the .dbscheme.
|
||||
* Use `NodeModule` from `NodeJS.qll` instead.
|
||||
*/
|
||||
deprecated predicate isNodejs(TopLevel toplevel) { is_nodejs(toplevel) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_es2015_module` defined in the .dbscheme.
|
||||
* Use `ES2015Module` from `ES2015Modules.qll` instead.
|
||||
*/
|
||||
deprecated predicate isES2015Module(TopLevel toplevel) { is_es2015_module(toplevel) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_closure_module` defined in the .dbscheme.
|
||||
*/
|
||||
deprecated predicate isClosureModule(TopLevel toplevel) { is_closure_module(toplevel) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `stmt_containers` defined in the .dbscheme.
|
||||
* Use `ASTNode#getContainer()` instead.
|
||||
*/
|
||||
deprecated predicate stmtContainers(Stmt stmt, StmtContainer container) {
|
||||
stmt_containers(stmt, container)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `jump_targets` defined in the .dbscheme.
|
||||
* Use `JumpStmt#getTarget()` instead.
|
||||
*/
|
||||
deprecated predicate jumpTargets(Stmt jump, Stmt target) { jump_targets(jump, target) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_instantiated` defined in the .dbscheme.
|
||||
* Use `NamespaceDeclaration#isInstantiated() instead.`
|
||||
*/
|
||||
deprecated predicate isInstantiated(NamespaceDeclaration decl) { is_instantiated(decl) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_declare_keyword` defined in the .dbscheme.
|
||||
*/
|
||||
deprecated predicate hasDeclareKeyword(ASTNode stmt) { has_declare_keyword(stmt) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_for_await_of` defined in the .dbscheme.
|
||||
* Use `ForOfStmt#isAwait()` instead.
|
||||
*/
|
||||
deprecated predicate isForAwaitOf(ForOfStmt forof) { is_for_await_of(forof) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `enclosing_stmt` defined in the .dbscheme.
|
||||
* Use `ExprOrType#getEnclosingStmt` instead.
|
||||
*/
|
||||
deprecated predicate enclosingStmt(ExprOrType expr, Stmt stmt) { enclosing_stmt(expr, stmt) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `expr_containers` defined in the .dbscheme.
|
||||
* Use `ASTNode#getContainer()` instead.
|
||||
*/
|
||||
deprecated predicate exprContainers(ExprOrType expr, StmtContainer container) {
|
||||
expr_containers(expr, container)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `array_size` defined in the .dbscheme.
|
||||
* Use `ArrayExpr#getSize()` instead.
|
||||
*/
|
||||
deprecated predicate arraySize(Expr ae, int sz) { array_size(ae, sz) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_delegating` defined in the .dbscheme.
|
||||
* Use `YieldExpr#isDelegating()` instead.
|
||||
*/
|
||||
deprecated predicate isDelegating(YieldExpr yield) { is_delegating(yield) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_arguments_object` defined in the .dbscheme.
|
||||
* Use the `ArgumentsVariable` class instead.
|
||||
*/
|
||||
deprecated predicate isArgumentsObject(Variable id) { is_arguments_object(id) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_computed` defined in the .dbscheme.
|
||||
* Use the `isComputed()` method on the `MemberDeclaration`/`Property`/`PropertyPattern` class instead.
|
||||
*/
|
||||
deprecated predicate isComputed(Property prop) { is_computed(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_method` defined in the .dbscheme.
|
||||
* Use the `isMethod()` method on the `MemberDeclaration`/`Property` class instead.
|
||||
*/
|
||||
deprecated predicate isMethod(Property prop) { is_method(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_static` defined in the .dbscheme.
|
||||
* Use `MemberDeclaration#isStatic()` instead.
|
||||
*/
|
||||
deprecated predicate isStatic(Property prop) { is_static(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_abstract_member` defined in the .dbscheme.
|
||||
* Use `MemberDeclaration#isAbstract()` instead.
|
||||
*/
|
||||
deprecated predicate isAbstractMember(Property prop) { is_abstract_member(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_const_enum` defined in the .dbscheme.
|
||||
* Use `EnumDeclaration#isConst()` instead.
|
||||
*/
|
||||
deprecated predicate isConstEnum(EnumDeclaration id) { is_const_enum(id) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_abstract_class` defined in the .dbscheme.
|
||||
* Use `ClassDefinition#isAbstract()` instead.
|
||||
*/
|
||||
deprecated predicate isAbstractClass(ClassDeclStmt id) { is_abstract_class(id) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_public_keyword` defined in the .dbscheme.
|
||||
* Use `MemberDeclaration#hasPublicKeyword() instead.
|
||||
*/
|
||||
deprecated predicate hasPublicKeyword(Property prop) { has_public_keyword(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_private_keyword` defined in the .dbscheme.
|
||||
* Use `MemberDeclaration#isPrivate() instead.
|
||||
*/
|
||||
deprecated predicate hasPrivateKeyword(Property prop) { has_private_keyword(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_protected_keyword` defined in the .dbscheme.
|
||||
* Use `MemberDeclaration#isProtected() instead.
|
||||
*/
|
||||
deprecated predicate hasProtectedKeyword(Property prop) { has_protected_keyword(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_readonly_keyword` defined in the .dbscheme.
|
||||
* Use `FieldDeclaration#isReadonly()` instead.
|
||||
*/
|
||||
deprecated predicate hasReadonlyKeyword(Property prop) { has_readonly_keyword(prop) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_type_keyword` defined in the .dbscheme.
|
||||
* Use the `isTypeOnly` method on the `ImportDeclaration`/`ExportDeclaration` classes instead.
|
||||
*/
|
||||
deprecated predicate hasTypeKeyword(ASTNode id) { has_type_keyword(id) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_optional_member` defined in the .dbscheme.
|
||||
* Use `FieldDeclaration#isOptional()` instead.
|
||||
*/
|
||||
deprecated predicate isOptionalMember(Property id) { is_optional_member(id) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_definite_assignment_assertion` defined in the .dbscheme.
|
||||
* Use the `hasDefiniteAssignmentAssertion` method on the `FieldDeclaration`/`VariableDeclarator` classes instead.
|
||||
*/
|
||||
deprecated predicate hasDefiniteAssignmentAssertion(ASTNode id) {
|
||||
has_definite_assignment_assertion(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_optional_parameter_declaration` defined in the .dbscheme.
|
||||
* Use `Parameter#isDeclaredOptional()` instead.
|
||||
*/
|
||||
deprecated predicate isOptionalParameterDeclaration(Parameter parameter) {
|
||||
is_optional_parameter_declaration(parameter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_asserts_keyword` defined in the .dbscheme.
|
||||
* Use `PredicateTypeExpr#hasAssertsKeyword() instead.
|
||||
*/
|
||||
deprecated predicate hasAssertsKeyword(PredicateTypeExpr node) { has_asserts_keyword(node) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `js_parse_errors` defined in the .dbscheme.
|
||||
* Use the `JSParseError` class instead.
|
||||
*/
|
||||
deprecated predicate jsParseErrors(JSParseError id, TopLevel toplevel, string message, string line) {
|
||||
js_parse_errors(id, toplevel, message, line)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `regexp_parse_errors` defined in the .dbscheme.
|
||||
* Use the `RegExpParseError` class instead.
|
||||
*/
|
||||
deprecated predicate regexpParseErrors(RegExpParseError id, RegExpTerm regexp, string message) {
|
||||
regexp_parse_errors(id, regexp, message)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_greedy` defined in the .dbscheme.
|
||||
* Use `RegExpQuantifier#isGreedy` instead.
|
||||
*/
|
||||
deprecated predicate isGreedy(RegExpQuantifier id) { is_greedy(id) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `range_quantifier_lower_bound` defined in the .dbscheme.
|
||||
* Use `RegExpRange#getLowerBound()` instead.
|
||||
*/
|
||||
deprecated predicate rangeQuantifierLowerBound(RegExpRange id, int lo) {
|
||||
range_quantifier_lower_bound(id, lo)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `range_quantifier_upper_bound` defined in the .dbscheme.
|
||||
* Use `RegExpRange#getUpperBound() instead.
|
||||
*/
|
||||
deprecated predicate rangeQuantifierUpperBound(RegExpRange id, int hi) {
|
||||
range_quantifier_upper_bound(id, hi)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_capture` defined in the .dbscheme.
|
||||
* Use `RegExpGroup#isCapture()` instead.
|
||||
*/
|
||||
deprecated predicate isCapture(RegExpGroup id, int number) { is_capture(id, number) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_named_capture` defined in the .dbscheme.
|
||||
* Use `RegExpGroup#isNamed()` instead.
|
||||
*/
|
||||
deprecated predicate isNamedCapture(RegExpGroup id, string name) { is_named_capture(id, name) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_inverted` defined in the .dbscheme.
|
||||
* Use `RegExpCharacterClass#isInverted()` instead.
|
||||
*/
|
||||
deprecated predicate isInverted(RegExpCharacterClass id) { is_inverted(id) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `regexp_const_value` defined in the .dbscheme.
|
||||
* Use `RegExpConstant#getValue()` instead.
|
||||
*/
|
||||
deprecated predicate regexpConstValue(RegExpConstant id, string value) {
|
||||
regexp_const_value(id, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `char_class_escape` defined in the .dbscheme.
|
||||
* Use `RegExpCharacterClassEscape#getValue()` instead.
|
||||
*/
|
||||
deprecated predicate charClassEscape(RegExpCharacterClassEscape id, string value) {
|
||||
char_class_escape(id, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `named_backref` defined in the .dbscheme.
|
||||
* Use `RegExpBackRef#getName()` instead.
|
||||
*/
|
||||
deprecated predicate namedBackref(RegExpBackRef id, string name) { named_backref(id, name) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `unicode_property_escapename` defined in the .dbscheme.
|
||||
* Use `RegExpUnicodePropertyEscape#getName()` instead.
|
||||
*/
|
||||
deprecated predicate unicodePropertyEscapeName(RegExpUnicodePropertyEscape id, string name) {
|
||||
unicode_property_escapename(id, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `unicode_property_escapevalue` defined in the .dbscheme.
|
||||
* Use `RegExpUnicodePropertyEscape#getValue()` instead.
|
||||
*/
|
||||
deprecated predicate unicodePropertyEscapeValue(RegExpUnicodePropertyEscape id, string value) {
|
||||
unicode_property_escapevalue(id, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_generator` defined in the .dbscheme.
|
||||
* Use `Function#isGenerator()` instead.
|
||||
*/
|
||||
deprecated predicate isGenerator(Function fun) { is_generator(fun) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `has_rest_parameter` defined in the .dbscheme.
|
||||
* Use `Function#hasRestParameter()` instead.
|
||||
*/
|
||||
deprecated predicate hasRestParameter(Function fun) { has_rest_parameter(fun) }
|
||||
|
||||
/**
|
||||
* Alias for the predicate `is_async` defined in the .dbscheme.
|
||||
* Use `Function#isAsync()` instead.
|
||||
*/
|
||||
deprecated predicate isAsync(Function fun) { is_async(fun) }
|
||||
|
||||
@@ -109,7 +109,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getMember(string m) {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::member(m))
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getUnknownMember() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::unknownMember())
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getAMember() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getMember(_)
|
||||
or
|
||||
result = this.getUnknownMember()
|
||||
@@ -148,7 +148,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getInstance() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::instance())
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getParameter(int i) {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::parameter(i))
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getReceiver() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::receiver())
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getAParameter() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getParameter(_)
|
||||
or
|
||||
result = this.getReceiver()
|
||||
@@ -210,7 +210,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getReturn() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::return())
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getPromised() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::promised())
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
Node getPromisedError() {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::promisedError())
|
||||
}
|
||||
|
||||
@@ -892,7 +892,7 @@ module API {
|
||||
*/
|
||||
cached
|
||||
predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) {
|
||||
Stages::APIStage::ref() and
|
||||
Stages::ApiStage::ref() and
|
||||
exists(string m |
|
||||
pred = MkRoot() and
|
||||
lbl = Label::moduleLabel(m)
|
||||
@@ -1251,7 +1251,7 @@ private predicate exports(string m, string prop, DataFlow::Node rhs) {
|
||||
|
||||
/** Gets the definition of module `m`. */
|
||||
private Module importableModule(string m) {
|
||||
exists(NPMPackage pkg, PackageJSON json | json = pkg.getPackageJSON() and not json.isPrivate() |
|
||||
exists(NpmPackage pkg, PackageJson json | json = pkg.getPackageJson() and not json.isPrivate() |
|
||||
result = pkg.getMainModule() and
|
||||
not result.isExterns() and
|
||||
m = pkg.getPackageName()
|
||||
|
||||
@@ -152,15 +152,12 @@ private module ArrayDataFlow {
|
||||
/**
|
||||
* A node that reads or writes an element from an array inside a for-loop.
|
||||
*/
|
||||
private class ArrayIndexingAccess extends DataFlow::Node {
|
||||
DataFlow::PropRef read;
|
||||
|
||||
private class ArrayIndexingAccess extends DataFlow::Node instanceof DataFlow::PropRef {
|
||||
ArrayIndexingAccess() {
|
||||
read = this and
|
||||
TTNumber() =
|
||||
unique(InferredType type | type = read.getPropertyNameExpr().flow().analyze().getAType()) and
|
||||
unique(InferredType type | type = super.getPropertyNameExpr().flow().analyze().getAType()) and
|
||||
exists(VarAccess i, ExprOrVarDecl init |
|
||||
i = read.getPropertyNameExpr() and init = any(ForStmt f).getInit()
|
||||
i = super.getPropertyNameExpr() and init = any(ForStmt f).getInit()
|
||||
|
|
||||
i.getVariable().getADefinition() = init or
|
||||
i.getVariable().getADefinition().(VariableDeclarator).getDeclStmt() = init
|
||||
|
||||
@@ -347,7 +347,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
||||
then result = "function in " + any(MethodDeclaration mem | mem.getBody() = this)
|
||||
else
|
||||
if this instanceof @decorator_list
|
||||
then result = "parameter decorators of " + this.(ASTNode).getParent().(Function).describe()
|
||||
then result = "parameter decorators of " + this.(AstNode).getParent().(Function).describe()
|
||||
else result = toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class CanonicalName extends @symbol {
|
||||
string getExternalModuleName() {
|
||||
symbol_module(this, result)
|
||||
or
|
||||
exists(PackageJSON pkg |
|
||||
exists(PackageJson pkg |
|
||||
getModule() = pkg.getMainModule() and
|
||||
result = pkg.getPackageName()
|
||||
)
|
||||
@@ -160,7 +160,7 @@ class CanonicalName extends @symbol {
|
||||
/**
|
||||
* Gets a definition of the entity with this canonical name.
|
||||
*/
|
||||
ASTNode getADefinition() { none() }
|
||||
AstNode getADefinition() { none() }
|
||||
|
||||
/**
|
||||
* Gets a use that refers to the entity with this canonical name.
|
||||
|
||||
@@ -32,7 +32,7 @@ module CharacterEscapes {
|
||||
* Holds if `n` is delimited by `delim` and contains `rawStringNode` with the raw string value `raw`.
|
||||
*/
|
||||
private predicate hasRawStringAndQuote(
|
||||
DataFlow::ValueNode n, string delim, ASTNode rawStringNode, string raw
|
||||
DataFlow::ValueNode n, string delim, AstNode rawStringNode, string raw
|
||||
) {
|
||||
rawStringNode = n.asExpr() and
|
||||
raw = rawStringNode.(StringLiteral).getRawValue() and
|
||||
@@ -52,7 +52,7 @@ module CharacterEscapes {
|
||||
*
|
||||
* The character is the `i`th character of `rawStringNode`'s raw string value.
|
||||
*/
|
||||
string getAnIdentityEscapedCharacter(DataFlow::Node n, ASTNode rawStringNode, int i) {
|
||||
string getAnIdentityEscapedCharacter(DataFlow::Node n, AstNode rawStringNode, int i) {
|
||||
exists(string delim, string raw, string additionalEscapeChars |
|
||||
hasRawStringAndQuote(n, delim, rawStringNode, raw) and
|
||||
if rawStringNode instanceof RegExpLiteral
|
||||
@@ -80,7 +80,7 @@ module CharacterEscapes {
|
||||
* The character is the `i`th character of the raw string value of `rawStringNode`.
|
||||
*/
|
||||
string getALikelyRegExpPatternMistake(
|
||||
RegExpPatternSource src, string mistake, ASTNode rawStringNode, int i
|
||||
RegExpPatternSource src, string mistake, AstNode rawStringNode, int i
|
||||
) {
|
||||
result = getAnIdentityEscapedCharacter(src, rawStringNode, i) and
|
||||
(
|
||||
|
||||
@@ -76,10 +76,10 @@ module DOM {
|
||||
/**
|
||||
* A JSX element, viewed as an `ElementDefinition`.
|
||||
*/
|
||||
private class JsxElementDefinition extends ElementDefinition, @jsx_element instanceof JSXElement {
|
||||
override string getName() { result = JSXElement.super.getName() }
|
||||
private class JsxElementDefinition extends ElementDefinition, @jsx_element instanceof JsxElement {
|
||||
override string getName() { result = JsxElement.super.getName() }
|
||||
|
||||
override AttributeDefinition getAttribute(int i) { result = JSXElement.super.getAttribute(i) }
|
||||
override AttributeDefinition getAttribute(int i) { result = JsxElement.super.getAttribute(i) }
|
||||
|
||||
override ElementDefinition getParent() { result = super.getJsxParent() }
|
||||
}
|
||||
@@ -139,7 +139,7 @@ module DOM {
|
||||
* A JSX attribute, viewed as an `AttributeDefinition`.
|
||||
*/
|
||||
private class JsxAttributeDefinition extends AttributeDefinition, @jsx_attribute {
|
||||
JSXAttribute attr;
|
||||
JsxAttribute attr;
|
||||
|
||||
JsxAttributeDefinition() { this = attr }
|
||||
|
||||
@@ -323,7 +323,7 @@ module DOM {
|
||||
|
||||
private class DefaultRange extends Range {
|
||||
DefaultRange() {
|
||||
this.asExpr().(VarAccess).getVariable() instanceof DOMGlobalVariable
|
||||
this.asExpr().(VarAccess).getVariable() instanceof DomGlobalVariable
|
||||
or
|
||||
exists(DataFlow::PropRead read |
|
||||
this = read and
|
||||
@@ -392,7 +392,7 @@ module DOM {
|
||||
*/
|
||||
private DataFlow::SourceNode domEventSource() {
|
||||
// e.g. <form onSubmit={e => e.target}/>
|
||||
exists(JSXAttribute attr | attr.getName().matches("on%") |
|
||||
exists(JsxAttribute attr | attr.getName().matches("on%") |
|
||||
result = attr.getValue().flow().getABoundFunctionValue(0).getParameter(0)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -249,8 +249,9 @@ class VarUse extends ControlFlowNode, @varref {
|
||||
/**
|
||||
* Holds if the definition of `v` in `def` reaches `use` along some control flow path
|
||||
* without crossing another definition of `v`.
|
||||
* DEPRECATED: Use the `SSA.qll` library instead.
|
||||
*/
|
||||
predicate definitionReaches(Variable v, VarDef def, VarUse use) {
|
||||
deprecated predicate definitionReaches(Variable v, VarDef def, VarUse use) {
|
||||
v = use.getVariable() and
|
||||
exists(BasicBlock bb, int i, int next | next = nextDefAfter(bb, v, i, def) |
|
||||
exists(int j | j in [i + 1 .. next - 1] | bb.useAt(j, v, use))
|
||||
@@ -265,16 +266,20 @@ predicate definitionReaches(Variable v, VarDef def, VarUse use) {
|
||||
/**
|
||||
* Holds if the definition of local variable `v` in `def` reaches `use` along some control flow path
|
||||
* without crossing another definition of `v`.
|
||||
* DEPRECATED: Use the `SSA.qll` library instead.
|
||||
*/
|
||||
predicate localDefinitionReaches(LocalVariable v, VarDef def, VarUse use) {
|
||||
deprecated predicate localDefinitionReaches(LocalVariable v, VarDef def, VarUse use) {
|
||||
exists(SsaExplicitDefinition ssa |
|
||||
ssa.defines(def, v) and
|
||||
ssa = getAPseudoDefinitionInput*(use.getSsaVariable().getDefinition())
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `nd` is a pseudo-definition and the result is one of its inputs. */
|
||||
private SsaDefinition getAPseudoDefinitionInput(SsaDefinition nd) {
|
||||
/**
|
||||
* Holds if `nd` is a pseudo-definition and the result is one of its inputs.
|
||||
* DEPRECATED: Use the `SSA.qll` library instead.
|
||||
*/
|
||||
deprecated private SsaDefinition getAPseudoDefinitionInput(SsaDefinition nd) {
|
||||
result = nd.(SsaPseudoDefinition).getAnInput()
|
||||
}
|
||||
|
||||
@@ -282,7 +287,7 @@ private SsaDefinition getAPseudoDefinitionInput(SsaDefinition nd) {
|
||||
* Holds if `d` is a definition of `v` at index `i` in `bb`, and the result is the next index
|
||||
* in `bb` after `i` at which the same variable is defined, or `bb.length()` if there is none.
|
||||
*/
|
||||
private int nextDefAfter(BasicBlock bb, Variable v, int i, VarDef d) {
|
||||
deprecated private int nextDefAfter(BasicBlock bb, Variable v, int i, VarDef d) {
|
||||
bb.defAt(i, v, d) and
|
||||
result =
|
||||
min(int jj |
|
||||
@@ -296,8 +301,9 @@ private int nextDefAfter(BasicBlock bb, Variable v, int i, VarDef d) {
|
||||
*
|
||||
* This is the case if there is a path from `earlier` to `later` that does not cross
|
||||
* another definition of `v`.
|
||||
* DEPRECATED: Use the `SSA.qll` library instead.
|
||||
*/
|
||||
predicate localDefinitionOverwrites(LocalVariable v, VarDef earlier, VarDef later) {
|
||||
deprecated predicate localDefinitionOverwrites(LocalVariable v, VarDef earlier, VarDef later) {
|
||||
exists(BasicBlock bb, int i, int next | next = nextDefAfter(bb, v, i, earlier) |
|
||||
bb.defAt(next, v, later)
|
||||
or
|
||||
|
||||
@@ -181,16 +181,7 @@ class DynamicPropRead extends DataFlow::SourceNode, DataFlow::ValueNode {
|
||||
* dst[x][y] = src[y];
|
||||
* ```
|
||||
*/
|
||||
predicate hasDominatingAssignment() {
|
||||
exists(DataFlow::PropWrite write, BasicBlock bb, int i, int j, SsaVariable ssaVar |
|
||||
write = getBase().getALocalSource().getAPropertyWrite() and
|
||||
bb.getNode(i) = write.getWriteNode() and
|
||||
bb.getNode(j) = astNode and
|
||||
i < j and
|
||||
write.getPropertyNameExpr() = ssaVar.getAUse() and
|
||||
astNode.getIndex() = ssaVar.getAUse()
|
||||
)
|
||||
}
|
||||
predicate hasDominatingAssignment() { AccessPath::DominatingPaths::hasDominatingWrite(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,10 @@ module E4X {
|
||||
* *
|
||||
* ```
|
||||
*/
|
||||
class XMLAnyName extends Expr, @e4x_xml_anyname { }
|
||||
class XmlAnyName extends Expr, @e4x_xml_anyname { }
|
||||
|
||||
/** DEPRECATED: Alias for XmlAnyName */
|
||||
deprecated class XMLAnyName = XmlAnyName;
|
||||
|
||||
/**
|
||||
* An E4X qualified identifier.
|
||||
@@ -29,7 +32,7 @@ module E4X {
|
||||
* Note that qualified identifiers are not currently supported by the parser, so snapshots
|
||||
* will not usually contain any.
|
||||
*/
|
||||
class XMLQualifiedIdentifier extends Expr, @e4x_xml_qualident {
|
||||
class XmlQualifiedIdentifier extends Expr, @e4x_xml_qualident {
|
||||
/**
|
||||
* Gets the left operand of this qualified identifier, which is either
|
||||
* an identifier or a wildcard.
|
||||
@@ -54,6 +57,9 @@ module E4X {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlQualifiedIdentifier */
|
||||
deprecated class XMLQualifiedIdentifier = XmlQualifiedIdentifier;
|
||||
|
||||
/**
|
||||
* An E4X attribute selector.
|
||||
*
|
||||
@@ -64,7 +70,7 @@ module E4X {
|
||||
* @[p]
|
||||
* ```
|
||||
*/
|
||||
class XMLAttributeSelector extends Expr, @e4x_xml_attribute_selector {
|
||||
class XmlAttributeSelector extends Expr, @e4x_xml_attribute_selector {
|
||||
/**
|
||||
* Gets the selected attribute, which is either a static name (that is, a
|
||||
* wildcard identifier or a possibly qualified name), or an arbitrary
|
||||
@@ -83,6 +89,9 @@ module E4X {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlAttributeSelector */
|
||||
deprecated class XMLAttributeSelector = XmlAttributeSelector;
|
||||
|
||||
/**
|
||||
* An E4X filter expression.
|
||||
*
|
||||
@@ -92,7 +101,7 @@ module E4X {
|
||||
* employees.(@id == 0 || @id == 1)
|
||||
* ```
|
||||
*/
|
||||
class XMLFilterExpression extends Expr, @e4x_xml_filter_expression {
|
||||
class XmlFilterExpression extends Expr, @e4x_xml_filter_expression {
|
||||
/**
|
||||
* Gets the left operand of this filter expression.
|
||||
*/
|
||||
@@ -108,6 +117,9 @@ module E4X {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlFilterExpression */
|
||||
deprecated class XMLFilterExpression = XmlFilterExpression;
|
||||
|
||||
/**
|
||||
* An E4X "dot-dot" expression.
|
||||
*
|
||||
@@ -117,7 +129,7 @@ module E4X {
|
||||
* e..name
|
||||
* ```
|
||||
*/
|
||||
class XMLDotDotExpression extends Expr, @e4x_xml_dotdotexpr {
|
||||
class XmlDotDotExpression extends Expr, @e4x_xml_dotdotexpr {
|
||||
/**
|
||||
* Gets the base expression of this dot-dot expression.
|
||||
*/
|
||||
@@ -132,4 +144,7 @@ module E4X {
|
||||
result = getBase().getFirstControlFlowNode()
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlDotDotExpression */
|
||||
deprecated class XMLDotDotExpression = XmlDotDotExpression;
|
||||
}
|
||||
|
||||
@@ -647,13 +647,6 @@ abstract class ReExportDeclaration extends ExportDeclaration {
|
||||
/** Gets the path of the module from which this declaration re-exports. */
|
||||
abstract ConstantString getImportedPath();
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `getReExportedES2015Module()` instead.
|
||||
*
|
||||
* Gets the module from which this declaration re-exports.
|
||||
*/
|
||||
deprecated ES2015Module getImportedModule() { result = getReExportedModule() }
|
||||
|
||||
/** Gets the module from which this declaration re-exports, if it is an ES2015 module. */
|
||||
ES2015Module getReExportedES2015Module() { result = getReExportedModule() }
|
||||
|
||||
|
||||
@@ -2744,7 +2744,7 @@ class Decorator extends @decorator, Expr {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Decoratable extends ASTNode {
|
||||
class Decoratable extends AstNode {
|
||||
Decoratable() {
|
||||
this instanceof ClassDefinition or
|
||||
this instanceof Property or
|
||||
|
||||
@@ -64,7 +64,7 @@ import javascript
|
||||
* Object.prototype.hasOwnProperty = function(p) {};
|
||||
* </pre>
|
||||
*/
|
||||
abstract class ExternalDecl extends ASTNode {
|
||||
abstract class ExternalDecl extends AstNode {
|
||||
/** Gets the name of this declaration. */
|
||||
abstract string getName();
|
||||
|
||||
@@ -125,7 +125,7 @@ abstract class ExternalVarDecl extends ExternalDecl {
|
||||
*
|
||||
* The result can be either a function or an expression.
|
||||
*/
|
||||
abstract ASTNode getInit();
|
||||
abstract AstNode getInit();
|
||||
|
||||
/**
|
||||
* Gets a JSDoc tag associated with this declaration.
|
||||
@@ -179,7 +179,7 @@ class ExternalGlobalFunctionDecl extends ExternalGlobalDecl, FunctionDeclStmt {
|
||||
/** Gets the name of this declaration. */
|
||||
override string getName() { result = FunctionDeclStmt.super.getName() }
|
||||
|
||||
override ASTNode getInit() { result = this }
|
||||
override AstNode getInit() { result = this }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,7 +336,7 @@ class ExternalInstanceMemberDecl extends ExternalMemberDecl {
|
||||
* function(p) {}; // external function entity
|
||||
* </pre>
|
||||
*/
|
||||
class ExternalEntity extends ASTNode {
|
||||
class ExternalEntity extends AstNode {
|
||||
ExternalEntity() { exists(ExternalVarDecl d | d.getInit() = this) }
|
||||
|
||||
/** Gets the variable declaration to which this entity belongs. */
|
||||
|
||||
@@ -7,31 +7,6 @@ private import semmle.javascript.dataflow.InferredTypes
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
|
||||
private import semmle.javascript.internal.CachedStages
|
||||
|
||||
deprecated module GlobalAccessPath {
|
||||
/**
|
||||
* DEPRECATED. Instead use `AccessPath::getAReferenceTo` with the result and parameter reversed.
|
||||
*/
|
||||
pragma[inline]
|
||||
string fromReference(DataFlow::Node node) { node = AccessPath::getAReferenceTo(result) }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Instead use `AccessPath::getAnAssignmentTo` with the result and parameter reversed.
|
||||
*/
|
||||
pragma[inline]
|
||||
string fromRhs(DataFlow::Node node) { node = AccessPath::getAnAssignmentTo(result) }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `AccessPath::getAReferenceOrAssignmentTo`.
|
||||
*/
|
||||
pragma[inline]
|
||||
string getAccessPath(DataFlow::Node node) {
|
||||
result = fromReference(node)
|
||||
or
|
||||
not exists(fromReference(node)) and
|
||||
result = fromRhs(node)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides predicates for associating access paths with data flow nodes.
|
||||
*
|
||||
@@ -557,7 +532,7 @@ module AccessPath {
|
||||
*/
|
||||
cached
|
||||
predicate hasDominatingWrite(DataFlow::PropRead read) {
|
||||
Stages::FlowSteps::ref() and
|
||||
Stages::TypeTracking::ref() and
|
||||
// within the same basic block.
|
||||
exists(ReachableBasicBlock bb, Root root, string path, int ranking |
|
||||
read.asExpr() = rankedAccessPath(bb, root, path, ranking, AccessPathRead()) and
|
||||
@@ -569,6 +544,21 @@ module AccessPath {
|
||||
read.asExpr() = getAccessTo(root, path, AccessPathRead()) and
|
||||
getAWriteBlock(root, path).strictlyDominates(read.getBasicBlock())
|
||||
)
|
||||
or
|
||||
// Dynamic write where the same variable is used to index the read and write (in the same basic block)
|
||||
// For example, this is true for `dst[x]` on line 2 below:
|
||||
// ```js
|
||||
// dst[x] = {};
|
||||
// dst[x][y] = src[y];
|
||||
// ```
|
||||
exists(DataFlow::PropWrite write, BasicBlock bb, int i, int j, SsaVariable ssaVar |
|
||||
write = read.getBase().getALocalSource().getAPropertyWrite() and
|
||||
bb.getNode(i) = write.getWriteNode() and
|
||||
bb.getNode(j) = read.asExpr() and
|
||||
i < j and
|
||||
write.getPropertyNameExpr() = ssaVar.getAUse() and
|
||||
read.getPropertyNameExpr() = ssaVar.getAUse()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class JSDoc extends @jsdoc, Locatable {
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
abstract class Documentable extends ASTNode {
|
||||
abstract class Documentable extends AstNode {
|
||||
/** Gets the JSDoc comment for this element, if any. */
|
||||
cached
|
||||
JSDoc getDocumentation() {
|
||||
|
||||
@@ -19,14 +19,14 @@ import javascript
|
||||
* { "value": 0 }
|
||||
* ```
|
||||
*/
|
||||
class JSONValue extends @json_value, Locatable {
|
||||
class JsonValue extends @json_value, Locatable {
|
||||
override Location getLocation() { json_locations(this, result) }
|
||||
|
||||
/** Gets the parent value to which this value belongs, if any. */
|
||||
JSONValue getParent() { json(this, _, result, _, _) }
|
||||
JsonValue getParent() { json(this, _, result, _, _) }
|
||||
|
||||
/** Gets the `i`th child value of this value. */
|
||||
JSONValue getChild(int i) { json(result, _, this, i, _) }
|
||||
JsonValue getChild(int i) { json(result, _, this, i, _) }
|
||||
|
||||
/** Holds if this JSON value is the top level element in its enclosing file. */
|
||||
predicate isTopLevel() { not exists(getParent()) }
|
||||
@@ -42,23 +42,26 @@ class JSONValue extends @json_value, Locatable {
|
||||
}
|
||||
|
||||
/** If this is an object, gets the value of property `name`. */
|
||||
JSONValue getPropValue(string name) { json_properties(this, name, result) }
|
||||
JsonValue getPropValue(string name) { json_properties(this, name, result) }
|
||||
|
||||
/** If this is an array, gets the value of the `i`th element. */
|
||||
JSONValue getElementValue(int i) { result = this.(JSONArray).getChild(i) }
|
||||
JsonValue getElementValue(int i) { result = this.(JsonArray).getChild(i) }
|
||||
|
||||
/** If this is a string constant, gets the value of the string. */
|
||||
string getStringValue() { result = this.(JSONString).getValue() }
|
||||
string getStringValue() { result = this.(JsonString).getValue() }
|
||||
|
||||
/** If this is an integer constant, gets its numeric value. */
|
||||
int getIntValue() { result = this.(JSONNumber).getValue().toInt() }
|
||||
int getIntValue() { result = this.(JsonNumber).getValue().toInt() }
|
||||
|
||||
/** If this is a boolean constant, gets its boolean value. */
|
||||
boolean getBooleanValue() { result.toString() = this.(JSONBoolean).getValue() }
|
||||
boolean getBooleanValue() { result.toString() = this.(JsonBoolean).getValue() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JSONValue" }
|
||||
override string getAPrimaryQlClass() { result = "JsonValue" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonValue */
|
||||
deprecated class JSONValue = JsonValue;
|
||||
|
||||
/**
|
||||
* A JSON-encoded primitive value.
|
||||
*
|
||||
@@ -72,7 +75,7 @@ class JSONValue extends @json_value, Locatable {
|
||||
* "a string"
|
||||
* ```
|
||||
*/
|
||||
abstract class JSONPrimitiveValue extends JSONValue {
|
||||
abstract class JsonPrimitiveValue extends JsonValue {
|
||||
/** Gets a string representation of the encoded value. */
|
||||
string getValue() { json_literals(result, _, this) }
|
||||
|
||||
@@ -80,6 +83,9 @@ abstract class JSONPrimitiveValue extends JSONValue {
|
||||
string getRawValue() { json_literals(_, result, this) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonPrimitiveValue */
|
||||
deprecated class JSONPrimitiveValue = JsonPrimitiveValue;
|
||||
|
||||
/**
|
||||
* A JSON-encoded null value.
|
||||
*
|
||||
@@ -89,10 +95,13 @@ abstract class JSONPrimitiveValue extends JSONValue {
|
||||
* null
|
||||
* ```
|
||||
*/
|
||||
class JSONNull extends @json_null, JSONPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JSONNull" }
|
||||
class JsonNull extends @json_null, JsonPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonNull" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonNull */
|
||||
deprecated class JSONNull = JsonNull;
|
||||
|
||||
/**
|
||||
* A JSON-encoded Boolean value.
|
||||
*
|
||||
@@ -103,10 +112,13 @@ class JSONNull extends @json_null, JSONPrimitiveValue {
|
||||
* false
|
||||
* ```
|
||||
*/
|
||||
class JSONBoolean extends @json_boolean, JSONPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JSONBoolean" }
|
||||
class JsonBoolean extends @json_boolean, JsonPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonBoolean" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonBoolean */
|
||||
deprecated class JSONBoolean = JsonBoolean;
|
||||
|
||||
/**
|
||||
* A JSON-encoded number.
|
||||
*
|
||||
@@ -117,10 +129,13 @@ class JSONBoolean extends @json_boolean, JSONPrimitiveValue {
|
||||
* 1.0
|
||||
* ```
|
||||
*/
|
||||
class JSONNumber extends @json_number, JSONPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JSONNumber" }
|
||||
class JsonNumber extends @json_number, JsonPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonNumber" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonNumber */
|
||||
deprecated class JSONNumber = JsonNumber;
|
||||
|
||||
/**
|
||||
* A JSON-encoded string value.
|
||||
*
|
||||
@@ -130,10 +145,13 @@ class JSONNumber extends @json_number, JSONPrimitiveValue {
|
||||
* "a string"
|
||||
* ```
|
||||
*/
|
||||
class JSONString extends @json_string, JSONPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JSONString" }
|
||||
class JsonString extends @json_string, JsonPrimitiveValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonString" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonString */
|
||||
deprecated class JSONString = JsonString;
|
||||
|
||||
/**
|
||||
* A JSON-encoded array.
|
||||
*
|
||||
@@ -143,13 +161,16 @@ class JSONString extends @json_string, JSONPrimitiveValue {
|
||||
* [ 1, 2, 3 ]
|
||||
* ```
|
||||
*/
|
||||
class JSONArray extends @json_array, JSONValue {
|
||||
override string getAPrimaryQlClass() { result = "JSONArray" }
|
||||
class JsonArray extends @json_array, JsonValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonArray" }
|
||||
|
||||
/** Gets the string value of the `i`th element of this array. */
|
||||
string getElementStringValue(int i) { result = getElementValue(i).getStringValue() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonArray */
|
||||
deprecated class JSONArray = JsonArray;
|
||||
|
||||
/**
|
||||
* A JSON-encoded object.
|
||||
*
|
||||
@@ -159,18 +180,24 @@ class JSONArray extends @json_array, JSONValue {
|
||||
* { "value": 0 }
|
||||
* ```
|
||||
*/
|
||||
class JSONObject extends @json_object, JSONValue {
|
||||
override string getAPrimaryQlClass() { result = "JSONObject" }
|
||||
class JsonObject extends @json_object, JsonValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonObject" }
|
||||
|
||||
/** Gets the string value of property `name` of this object. */
|
||||
string getPropStringValue(string name) { result = getPropValue(name).getStringValue() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonObject */
|
||||
deprecated class JSONObject = JsonObject;
|
||||
|
||||
/**
|
||||
* An error reported by the JSON parser.
|
||||
*/
|
||||
class JSONParseError extends @json_parse_error, Error {
|
||||
class JsonParseError extends @json_parse_error, Error {
|
||||
override Location getLocation() { json_locations(this, result) }
|
||||
|
||||
override string getMessage() { json_errors(this, result) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonParseError */
|
||||
deprecated class JSONParseError = JsonParseError;
|
||||
|
||||
@@ -15,7 +15,7 @@ import javascript
|
||||
* <><h1>Title</h1>Some <b>text</b></>
|
||||
* ```
|
||||
*/
|
||||
class JSXNode extends Expr, @jsx_element {
|
||||
class JsxNode extends Expr, @jsx_element {
|
||||
/** Gets the `i`th element in the body of this element or fragment. */
|
||||
Expr getBodyElement(int i) { i >= 0 and result = getChildExpr(-i - 2) }
|
||||
|
||||
@@ -25,11 +25,14 @@ class JSXNode extends Expr, @jsx_element {
|
||||
/**
|
||||
* Gets the parent JSX element or fragment of this element.
|
||||
*/
|
||||
JSXNode getJsxParent() { this = result.getABodyElement() }
|
||||
JsxNode getJsxParent() { this = result.getABodyElement() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JSXNode" }
|
||||
override string getAPrimaryQlClass() { result = "JsxNode" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxNode */
|
||||
deprecated class JSXNode = JsxNode;
|
||||
|
||||
/**
|
||||
* A JSX element.
|
||||
*
|
||||
@@ -40,39 +43,45 @@ class JSXNode extends Expr, @jsx_element {
|
||||
* <Welcome name={user.name}/>
|
||||
* ```
|
||||
*/
|
||||
class JSXElement extends JSXNode {
|
||||
JSXName name;
|
||||
class JsxElement extends JsxNode {
|
||||
JsxName name;
|
||||
|
||||
JSXElement() { name = getChildExpr(-1) }
|
||||
JsxElement() { name = getChildExpr(-1) }
|
||||
|
||||
/** Gets the expression denoting the name of this element. */
|
||||
JSXName getNameExpr() { result = name }
|
||||
JsxName getNameExpr() { result = name }
|
||||
|
||||
/** Gets the name of this element. */
|
||||
string getName() { result = name.getValue() }
|
||||
|
||||
/** Gets the `i`th attribute of this element. */
|
||||
JSXAttribute getAttribute(int i) { properties(result, this, i, _, _) }
|
||||
JsxAttribute getAttribute(int i) { properties(result, this, i, _, _) }
|
||||
|
||||
/** Gets an attribute of this element. */
|
||||
JSXAttribute getAnAttribute() { result = getAttribute(_) }
|
||||
JsxAttribute getAnAttribute() { result = getAttribute(_) }
|
||||
|
||||
/** Gets the attribute of this element with the given name, if any. */
|
||||
JSXAttribute getAttributeByName(string n) { result = getAnAttribute() and result.getName() = n }
|
||||
JsxAttribute getAttributeByName(string n) { result = getAnAttribute() and result.getName() = n }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getNameExpr().getFirstControlFlowNode()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JSXElement" }
|
||||
override string getAPrimaryQlClass() { result = "JsxElement" }
|
||||
|
||||
/**
|
||||
* Holds if this JSX element is a HTML element.
|
||||
* That is, the name starts with a lowercase letter.
|
||||
*/
|
||||
predicate isHTMLElement() { getName().regexpMatch("[a-z].*") }
|
||||
predicate isHtmlElement() { getName().regexpMatch("[a-z].*") }
|
||||
|
||||
/** DEPRECATED: Alias for isHtmlElement */
|
||||
deprecated predicate isHTMLElement() { isHtmlElement() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxElement */
|
||||
deprecated class JSXElement = JsxElement;
|
||||
|
||||
/**
|
||||
* A JSX fragment.
|
||||
*
|
||||
@@ -82,8 +91,8 @@ class JSXElement extends JSXNode {
|
||||
* <><h1>Title</h1>Some <b>text</b></>
|
||||
* ```
|
||||
*/
|
||||
class JSXFragment extends JSXNode {
|
||||
JSXFragment() { not exists(getChildExpr(-1)) }
|
||||
class JsxFragment extends JsxNode {
|
||||
JsxFragment() { not exists(getChildExpr(-1)) }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getBodyElement(0).getFirstControlFlowNode()
|
||||
@@ -91,9 +100,12 @@ class JSXFragment extends JSXNode {
|
||||
not exists(getABodyElement()) and result = this
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JSXFragment" }
|
||||
override string getAPrimaryQlClass() { result = "JsxFragment" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxFragment */
|
||||
deprecated class JSXFragment = JsxFragment;
|
||||
|
||||
/**
|
||||
* An attribute of a JSX element, including spread attributes.
|
||||
*
|
||||
@@ -105,13 +117,13 @@ class JSXFragment extends JSXNode {
|
||||
* <div {...attrs}></div> // `{...attrs}` is a (spread) attribute
|
||||
* ```
|
||||
*/
|
||||
class JSXAttribute extends ASTNode, @jsx_attribute {
|
||||
class JsxAttribute extends AstNode, @jsx_attribute {
|
||||
/**
|
||||
* Gets the expression denoting the name of this attribute.
|
||||
*
|
||||
* This is not defined for spread attributes.
|
||||
*/
|
||||
JSXName getNameExpr() { result = getChildExpr(0) }
|
||||
JsxName getNameExpr() { result = getChildExpr(0) }
|
||||
|
||||
/**
|
||||
* Gets the name of this attribute.
|
||||
@@ -127,7 +139,7 @@ class JSXAttribute extends ASTNode, @jsx_attribute {
|
||||
string getStringValue() { result = getValue().getStringValue() }
|
||||
|
||||
/** Gets the JSX element to which this attribute belongs. */
|
||||
JSXElement getElement() { this = result.getAnAttribute() }
|
||||
JsxElement getElement() { this = result.getAnAttribute() }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getNameExpr().getFirstControlFlowNode()
|
||||
@@ -137,9 +149,12 @@ class JSXAttribute extends ASTNode, @jsx_attribute {
|
||||
|
||||
override string toString() { properties(this, _, _, _, result) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JSXAttribute" }
|
||||
override string getAPrimaryQlClass() { result = "JsxAttribute" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxAttribute */
|
||||
deprecated class JSXAttribute = JsxAttribute;
|
||||
|
||||
/**
|
||||
* A spread attribute of a JSX element.
|
||||
*
|
||||
@@ -149,8 +164,8 @@ class JSXAttribute extends ASTNode, @jsx_attribute {
|
||||
* <div {...attrs}></div> // `{...attrs}` is a spread attribute
|
||||
* ```
|
||||
*/
|
||||
class JSXSpreadAttribute extends JSXAttribute {
|
||||
JSXSpreadAttribute() { not exists(getNameExpr()) }
|
||||
class JsxSpreadAttribute extends JsxAttribute {
|
||||
JsxSpreadAttribute() { not exists(getNameExpr()) }
|
||||
|
||||
override SpreadElement getValue() {
|
||||
// override for more precise result type
|
||||
@@ -158,6 +173,9 @@ class JSXSpreadAttribute extends JSXAttribute {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxSpreadAttribute */
|
||||
deprecated class JSXSpreadAttribute = JsxSpreadAttribute;
|
||||
|
||||
/**
|
||||
* A namespace-qualified name such as `n:a`.
|
||||
*
|
||||
@@ -167,7 +185,7 @@ class JSXSpreadAttribute extends JSXAttribute {
|
||||
* html:href
|
||||
* ```
|
||||
*/
|
||||
class JSXQualifiedName extends Expr, @jsx_qualified_name {
|
||||
class JsxQualifiedName extends Expr, @jsx_qualified_name {
|
||||
/** Gets the namespace component of this qualified name. */
|
||||
Identifier getNamespace() { result = getChildExpr(0) }
|
||||
|
||||
@@ -178,9 +196,12 @@ class JSXQualifiedName extends Expr, @jsx_qualified_name {
|
||||
result = getNamespace().getFirstControlFlowNode()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JSXQualifiedName" }
|
||||
override string getAPrimaryQlClass() { result = "JsxQualifiedName" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxQualifiedName */
|
||||
deprecated class JSXQualifiedName = JsxQualifiedName;
|
||||
|
||||
/**
|
||||
* A name of an JSX element or attribute (which is
|
||||
* always an identifier, a dot expression, or a qualified
|
||||
@@ -194,12 +215,12 @@ class JSXQualifiedName extends Expr, @jsx_qualified_name {
|
||||
* data.path
|
||||
* ```
|
||||
*/
|
||||
class JSXName extends Expr {
|
||||
JSXName() {
|
||||
class JsxName extends Expr {
|
||||
JsxName() {
|
||||
this instanceof Identifier or
|
||||
this instanceof ThisExpr or
|
||||
this.(DotExpr).getBase() instanceof JSXName or
|
||||
this instanceof JSXQualifiedName
|
||||
this.(DotExpr).getBase() instanceof JsxName or
|
||||
this instanceof JsxQualifiedName
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,10 +230,10 @@ class JSXName extends Expr {
|
||||
result = this.(Identifier).getName()
|
||||
or
|
||||
exists(DotExpr dot | dot = this |
|
||||
result = dot.getBase().(JSXName).getValue() + "." + dot.getPropertyName()
|
||||
result = dot.getBase().(JsxName).getValue() + "." + dot.getPropertyName()
|
||||
)
|
||||
or
|
||||
exists(JSXQualifiedName qual | qual = this |
|
||||
exists(JsxQualifiedName qual | qual = this |
|
||||
result = qual.getNamespace().getName() + ":" + qual.getName().getName()
|
||||
)
|
||||
or
|
||||
@@ -221,6 +242,9 @@ class JSXName extends Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxName */
|
||||
deprecated class JSXName = JsxName;
|
||||
|
||||
/**
|
||||
* An interpolating expression that interpolates nothing.
|
||||
*
|
||||
@@ -230,10 +254,13 @@ class JSXName extends Expr {
|
||||
* { /* TBD */ }
|
||||
* </pre>
|
||||
*/
|
||||
class JSXEmptyExpr extends Expr, @jsx_empty_expr {
|
||||
override string getAPrimaryQlClass() { result = "JSXEmptyExpr" }
|
||||
class JsxEmptyExpr extends Expr, @jsx_empty_expr {
|
||||
override string getAPrimaryQlClass() { result = "JsxEmptyExpr" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxEmptyExpr */
|
||||
deprecated class JSXEmptyExpr = JsxEmptyExpr;
|
||||
|
||||
/**
|
||||
* A legacy `@jsx` pragma.
|
||||
*
|
||||
@@ -243,12 +270,18 @@ class JSXEmptyExpr extends Expr, @jsx_empty_expr {
|
||||
* @jsx React.DOM
|
||||
* ```
|
||||
*/
|
||||
class JSXPragma extends JSDocTag {
|
||||
JSXPragma() { getTitle() = "jsx" }
|
||||
class JsxPragma extends JSDocTag {
|
||||
JsxPragma() { getTitle() = "jsx" }
|
||||
|
||||
/**
|
||||
* Gets the DOM name specified by the pragma; for `@jsx React.DOM`,
|
||||
* the result is `React.DOM`.
|
||||
*/
|
||||
string getDOMName() { result = getDescription().trim() }
|
||||
string getDomName() { result = getDescription().trim() }
|
||||
|
||||
/** DEPRECATED: Alias for getDomName */
|
||||
deprecated string getDOMName() { result = getDomName() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxPragma */
|
||||
deprecated class JSXPragma = JsxPragma;
|
||||
|
||||
@@ -64,7 +64,7 @@ class JSON2CSVTaintStep extends TaintTracking::SharedTaintStep {
|
||||
* This is not quite a `JSON.stringify` call, as it e.g. does not wrap keys in double quotes.
|
||||
* It's therefore modeled as a taint-step rather than as a `JSON.stringify` call.
|
||||
*/
|
||||
class PrettyJSONTaintStep extends TaintTracking::SharedTaintStep {
|
||||
class PrettyJsonTaintStep extends TaintTracking::SharedTaintStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(API::CallNode call |
|
||||
call = API::moduleImport("prettyjson").getMember("render").getACall()
|
||||
@@ -74,3 +74,6 @@ class PrettyJSONTaintStep extends TaintTracking::SharedTaintStep {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PrettyJsonTaintStep */
|
||||
deprecated class PrettyJSONTaintStep = PrettyJsonTaintStep;
|
||||
|
||||
@@ -27,76 +27,6 @@ abstract class Module extends TopLevel {
|
||||
/** Gets a symbol exported by this module. */
|
||||
string getAnExportedSymbol() { exists(this.getAnExportedValue(result)) }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `getAnExportedValue` instead.
|
||||
*
|
||||
* Holds if this module explicitly exports symbol `name` at the
|
||||
* program element `export`.
|
||||
*
|
||||
* Note that in some module systems (notably CommonJS and AMD)
|
||||
* modules are arbitrary objects that export all their
|
||||
* properties. This predicate only considers properties
|
||||
* that are explicitly defined on the module object.
|
||||
*
|
||||
* Symbols defined in another module that are re-exported by
|
||||
* this module are only sometimes considered.
|
||||
*/
|
||||
deprecated predicate exports(string name, ASTNode export) {
|
||||
this instanceof AmdModule and
|
||||
exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() |
|
||||
pwn.getBase().analyze().getAValue() = this.(AmdModule).getDefine().getAModuleExportsValue() and
|
||||
name = pwn.getPropertyName()
|
||||
)
|
||||
or
|
||||
this instanceof Closure::ClosureModule and
|
||||
exists(DataFlow::PropWrite write, Expr base |
|
||||
write.getAstNode() = export and
|
||||
write.writes(base.flow(), name, _) and
|
||||
(
|
||||
base = this.(Closure::ClosureModule).getExportsVariable().getAReference()
|
||||
or
|
||||
base = this.(Closure::ClosureModule).getExportsVariable().getAnAssignedExpr()
|
||||
)
|
||||
)
|
||||
or
|
||||
this instanceof NodeModule and
|
||||
(
|
||||
// a property write whose base is `exports` or `module.exports`
|
||||
exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() |
|
||||
pwn.getBase() = this.(NodeModule).getAModuleExportsNode() and
|
||||
name = pwn.getPropertyName()
|
||||
)
|
||||
or
|
||||
// a re-export using spread-operator. E.g. `const foo = require("./foo"); module.exports = {bar: bar, ...foo};`
|
||||
exists(ObjectExpr obj | obj = this.(NodeModule).getAModuleExportsNode().asExpr() |
|
||||
obj.getAProperty()
|
||||
.(SpreadProperty)
|
||||
.getInit()
|
||||
.(SpreadElement)
|
||||
.getOperand()
|
||||
.flow()
|
||||
.getALocalSource()
|
||||
.asExpr()
|
||||
.(Import)
|
||||
.getImportedModule()
|
||||
.exports(name, export)
|
||||
)
|
||||
or
|
||||
// an externs definition (where appropriate)
|
||||
exists(PropAccess pacc | export = pacc |
|
||||
pacc.getBase() = this.(NodeModule).getAModuleExportsNode().asExpr() and
|
||||
name = pacc.getPropertyName() and
|
||||
this.isExterns() and
|
||||
exists(pacc.getDocumentation())
|
||||
)
|
||||
)
|
||||
or
|
||||
this instanceof ES2015Module and
|
||||
exists(ExportDeclaration ed | ed = this.(ES2015Module).getAnExport() and ed = export |
|
||||
ed.exportsAs(_, name)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value that is explicitly exported from this module with under `name`.
|
||||
*
|
||||
@@ -188,7 +118,7 @@ abstract class Module extends TopLevel {
|
||||
* An import in a module, which may be an ECMAScript 2015-style
|
||||
* `import` statement, a CommonJS-style `require` import, or an AMD dependency.
|
||||
*/
|
||||
abstract class Import extends ASTNode {
|
||||
abstract class Import extends AstNode {
|
||||
/** Gets the module in which this import appears. */
|
||||
abstract Module getEnclosingModule();
|
||||
|
||||
@@ -275,26 +205,13 @@ abstract class Import extends ASTNode {
|
||||
abstract DataFlow::Node getImportedModuleNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `PathExpr` instead.
|
||||
*
|
||||
* A path expression that appears in a module and is resolved relative to it.
|
||||
*/
|
||||
abstract deprecated class PathExprInModule extends PathExpr {
|
||||
PathExprInModule() {
|
||||
this.(Expr).getTopLevel() instanceof Module
|
||||
or
|
||||
this.(Comment).getTopLevel() instanceof Module
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a module imported from another package in the same repository.
|
||||
*
|
||||
* No support for importing from folders inside the other package.
|
||||
*/
|
||||
private Module resolveNeighbourPackage(PathString importPath) {
|
||||
exists(PackageJSON json | importPath = json.getPackageName() and result = json.getMainModule())
|
||||
exists(PackageJson json | importPath = json.getPackageName() and result = json.getMainModule())
|
||||
or
|
||||
exists(string package |
|
||||
result.getFile().getParentContainer() = getPackageFolder(package) and
|
||||
@@ -307,7 +224,7 @@ private Module resolveNeighbourPackage(PathString importPath) {
|
||||
*/
|
||||
pragma[noinline]
|
||||
private Folder getPackageFolder(string package) {
|
||||
exists(PackageJSON json |
|
||||
exists(PackageJson json |
|
||||
json.getPackageName() = package and
|
||||
result = json.getFile().getParentContainer()
|
||||
)
|
||||
|
||||
@@ -6,8 +6,8 @@ import javascript
|
||||
private import NodeModuleResolutionImpl
|
||||
|
||||
/** A `package.json` configuration object. */
|
||||
class PackageJSON extends JSONObject {
|
||||
PackageJSON() {
|
||||
class PackageJson extends JsonObject {
|
||||
PackageJson() {
|
||||
this.getJsonFile().getBaseName() = "package.json" and
|
||||
this.isTopLevel()
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class PackageJSON extends JSONObject {
|
||||
string getDescription() { result = this.getPropStringValue("description") }
|
||||
|
||||
/** Gets the array of keywords for this package. */
|
||||
JSONArray getKeywords() { result = this.getPropValue("keywords") }
|
||||
JsonArray getKeywords() { result = this.getPropValue("keywords") }
|
||||
|
||||
/** Gets a keyword for this package. */
|
||||
string getAKeyword() { result = this.getKeywords().getElementStringValue(_) }
|
||||
@@ -45,7 +45,7 @@ class PackageJSON extends JSONObject {
|
||||
}
|
||||
|
||||
/** Gets the array of files for this package. */
|
||||
JSONArray getFiles() { result = this.getPropValue("files") }
|
||||
JsonArray getFiles() { result = this.getPropValue("files") }
|
||||
|
||||
/** Gets a file for this package. */
|
||||
string getAFile() { result = this.getFiles().getElementStringValue(_) }
|
||||
@@ -67,16 +67,16 @@ class PackageJSON extends JSONObject {
|
||||
}
|
||||
|
||||
/** Gets information about the directories of this package. */
|
||||
JSONObject getDirectories() { result = this.getPropValue("directories") }
|
||||
JsonObject getDirectories() { result = this.getPropValue("directories") }
|
||||
|
||||
/** Gets repository information for this package. */
|
||||
RepositoryInfo getRepository() { result = this.getPropValue("repository") }
|
||||
|
||||
/** Gets information about the scripts of this package. */
|
||||
JSONObject getScripts() { result = this.getPropValue("scripts") }
|
||||
JsonObject getScripts() { result = this.getPropValue("scripts") }
|
||||
|
||||
/** Gets configuration information for this package. */
|
||||
JSONObject getConfig() { result = this.getPropValue("config") }
|
||||
JsonObject getConfig() { result = this.getPropValue("config") }
|
||||
|
||||
/** Gets the dependencies of this package. */
|
||||
PackageDependencies getDependencies() { result = this.getPropValue("dependencies") }
|
||||
@@ -131,10 +131,10 @@ class PackageJSON extends JSONObject {
|
||||
PackageDependencies getEngines() { result = this.getPropValue("engines") }
|
||||
|
||||
/** Holds if this package has strict engine requirements. */
|
||||
predicate isEngineStrict() { this.getPropValue("engineStrict").(JSONBoolean).getValue() = "true" }
|
||||
predicate isEngineStrict() { this.getPropValue("engineStrict").(JsonBoolean).getValue() = "true" }
|
||||
|
||||
/** Gets information about operating systems supported by this package. */
|
||||
JSONArray getOSs() { result = this.getPropValue("os") }
|
||||
JsonArray getOSs() { result = this.getPropValue("os") }
|
||||
|
||||
/** Gets an operating system supported by this package. */
|
||||
string getWhitelistedOS() {
|
||||
@@ -150,7 +150,7 @@ class PackageJSON extends JSONObject {
|
||||
}
|
||||
|
||||
/** Gets information about platforms supported by this package. */
|
||||
JSONArray getCPUs() { result = this.getPropValue("cpu") }
|
||||
JsonArray getCPUs() { result = this.getPropValue("cpu") }
|
||||
|
||||
/** Gets a platform supported by this package. */
|
||||
string getWhitelistedCPU() {
|
||||
@@ -166,13 +166,13 @@ class PackageJSON extends JSONObject {
|
||||
}
|
||||
|
||||
/** Holds if this package prefers to be installed globally. */
|
||||
predicate isPreferGlobal() { this.getPropValue("preferGlobal").(JSONBoolean).getValue() = "true" }
|
||||
predicate isPreferGlobal() { this.getPropValue("preferGlobal").(JsonBoolean).getValue() = "true" }
|
||||
|
||||
/** Holds if this is a private package. */
|
||||
predicate isPrivate() { this.getPropValue("private").(JSONBoolean).getValue() = "true" }
|
||||
predicate isPrivate() { this.getPropValue("private").(JsonBoolean).getValue() = "true" }
|
||||
|
||||
/** Gets publishing configuration information about this package. */
|
||||
JSONValue getPublishConfig() { result = this.getPropValue("publishConfig") }
|
||||
JsonValue getPublishConfig() { result = this.getPropValue("publishConfig") }
|
||||
|
||||
/**
|
||||
* Gets the main module of this package.
|
||||
@@ -182,13 +182,16 @@ class PackageJSON extends JSONObject {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PackageJson */
|
||||
deprecated class PackageJSON = PackageJson;
|
||||
|
||||
/**
|
||||
* A representation of bug tracker information for an NPM package.
|
||||
*/
|
||||
class BugTrackerInfo extends JSONValue {
|
||||
class BugTrackerInfo extends JsonValue {
|
||||
BugTrackerInfo() {
|
||||
exists(PackageJSON pkg | pkg.getPropValue("bugs") = this) and
|
||||
(this instanceof JSONObject or this instanceof JSONString)
|
||||
exists(PackageJson pkg | pkg.getPropValue("bugs") = this) and
|
||||
(this instanceof JsonObject or this instanceof JsonString)
|
||||
}
|
||||
|
||||
/** Gets the bug tracker URL. */
|
||||
@@ -204,13 +207,13 @@ class BugTrackerInfo extends JSONValue {
|
||||
/**
|
||||
* A representation of contributor information for an NPM package.
|
||||
*/
|
||||
class ContributorInfo extends JSONValue {
|
||||
class ContributorInfo extends JsonValue {
|
||||
ContributorInfo() {
|
||||
exists(PackageJSON pkg |
|
||||
exists(PackageJson pkg |
|
||||
this = pkg.getPropValue("author") or
|
||||
this = pkg.getPropValue("contributors").getElementValue(_)
|
||||
) and
|
||||
(this instanceof JSONObject or this instanceof JSONString)
|
||||
(this instanceof JsonObject or this instanceof JsonString)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,8 +247,8 @@ class ContributorInfo extends JSONValue {
|
||||
/**
|
||||
* A representation of repository information for an NPM package.
|
||||
*/
|
||||
class RepositoryInfo extends JSONObject {
|
||||
RepositoryInfo() { exists(PackageJSON pkg | this = pkg.getPropValue("repository")) }
|
||||
class RepositoryInfo extends JsonObject {
|
||||
RepositoryInfo() { exists(PackageJson pkg | this = pkg.getPropValue("repository")) }
|
||||
|
||||
/** Gets the repository type. */
|
||||
string getType() { result = this.getPropStringValue("type") }
|
||||
@@ -257,9 +260,9 @@ class RepositoryInfo extends JSONObject {
|
||||
/**
|
||||
* A representation of package dependencies for an NPM package.
|
||||
*/
|
||||
class PackageDependencies extends JSONObject {
|
||||
class PackageDependencies extends JsonObject {
|
||||
PackageDependencies() {
|
||||
exists(PackageJSON pkg, string name |
|
||||
exists(PackageJson pkg, string name |
|
||||
name.regexpMatch("(.+D|d)ependencies|engines") and
|
||||
this = pkg.getPropValue(name)
|
||||
)
|
||||
@@ -272,11 +275,11 @@ class PackageDependencies extends JSONObject {
|
||||
/**
|
||||
* An NPM package.
|
||||
*/
|
||||
class NPMPackage extends @folder {
|
||||
class NpmPackage extends @folder {
|
||||
/** The `package.json` file of this package. */
|
||||
PackageJSON pkg;
|
||||
PackageJson pkg;
|
||||
|
||||
NPMPackage() { pkg.getJsonFile().getParentContainer() = this }
|
||||
NpmPackage() { pkg.getJsonFile().getParentContainer() = this }
|
||||
|
||||
/** Gets a textual representation of this package. */
|
||||
string toString() { result = this.(Folder).toString() }
|
||||
@@ -285,10 +288,13 @@ class NPMPackage extends @folder {
|
||||
string getPath() { result = this.(Folder).getAbsolutePath() }
|
||||
|
||||
/** Gets the `package.json` object of this package. */
|
||||
PackageJSON getPackageJSON() { result = pkg }
|
||||
PackageJson getPackageJson() { result = pkg }
|
||||
|
||||
/** DEPRECATED: Alias for getPackageJson */
|
||||
deprecated PackageJSON getPackageJSON() { result = this.getPackageJson() }
|
||||
|
||||
/** Gets the name of this package. */
|
||||
string getPackageName() { result = this.getPackageJSON().getPackageName() }
|
||||
string getPackageName() { result = this.getPackageJson().getPackageName() }
|
||||
|
||||
/** Gets the `node_modules` folder of this package. */
|
||||
Folder getNodeModulesFolder() {
|
||||
@@ -325,6 +331,9 @@ class NPMPackage extends @folder {
|
||||
predicate declaresDependency(string p, string v) { pkg.declaresDependency(p, v) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for NpmPackage */
|
||||
deprecated class NPMPackage = NpmPackage;
|
||||
|
||||
/**
|
||||
* Gets the parent folder of `c`, provided that they belong to the same NPM
|
||||
* package; that is, `c` must not be a `node_modules` folder.
|
||||
|
||||
@@ -60,7 +60,7 @@ File loadAsFile(Require req, int rootPriority, int priority) {
|
||||
*/
|
||||
File loadAsDirectory(Require req, int rootPriority, int priority) {
|
||||
exists(Folder dir | dir = req.getImportedPath().resolve(rootPriority) |
|
||||
result = resolveMainModule(dir.(NPMPackage).getPackageJSON(), priority) or
|
||||
result = resolveMainModule(dir.(NpmPackage).getPackageJson(), priority) or
|
||||
result = tryExtensions(dir, "index", priority - (numberOfExtensions() + 1))
|
||||
)
|
||||
}
|
||||
@@ -90,7 +90,7 @@ private string getStem(string name) { result = name.regexpCapture("(.+?)(?:\\.([
|
||||
/**
|
||||
* Gets the main module described by `pkg` with the given `priority`.
|
||||
*/
|
||||
File resolveMainModule(PackageJSON pkg, int priority) {
|
||||
File resolveMainModule(PackageJson pkg, int priority) {
|
||||
exists(PathExpr main | main = MainModulePath::of(pkg) |
|
||||
result = main.resolve() and priority = 0
|
||||
or
|
||||
@@ -144,14 +144,17 @@ private string getASrcFolderName() { result = ["ts", "js", "src", "lib"] }
|
||||
* module of the package.
|
||||
*/
|
||||
class MainModulePath extends PathExpr, @json_string {
|
||||
PackageJSON pkg;
|
||||
PackageJson pkg;
|
||||
|
||||
MainModulePath() { this = pkg.getPropValue(["main", "module"]) }
|
||||
|
||||
/** Gets the `package.json` file in which this path occurs. */
|
||||
PackageJSON getPackageJSON() { result = pkg }
|
||||
PackageJson getPackageJson() { result = pkg }
|
||||
|
||||
override string getValue() { result = this.(JSONString).getValue() }
|
||||
/** DEPRECATED: Alias for getPackageJson */
|
||||
deprecated PackageJSON getPackageJSON() { result = getPackageJson() }
|
||||
|
||||
override string getValue() { result = this.(JsonString).getValue() }
|
||||
|
||||
override Folder getAdditionalSearchRoot(int priority) {
|
||||
priority = 0 and
|
||||
@@ -160,7 +163,7 @@ class MainModulePath extends PathExpr, @json_string {
|
||||
}
|
||||
|
||||
module MainModulePath {
|
||||
MainModulePath of(PackageJSON pkg) { result.getPackageJSON() = pkg }
|
||||
MainModulePath of(PackageJson pkg) { result.getPackageJson() = pkg }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,17 +172,20 @@ module MainModulePath {
|
||||
* For performance reasons this only exists if there is no "main" field in the `package.json` file.
|
||||
*/
|
||||
private class FilesPath extends PathExpr, @json_string {
|
||||
PackageJSON pkg;
|
||||
PackageJson pkg;
|
||||
|
||||
FilesPath() {
|
||||
this = pkg.getPropValue("files").(JSONArray).getElementValue(_) and
|
||||
this = pkg.getPropValue("files").(JsonArray).getElementValue(_) and
|
||||
not exists(MainModulePath::of(pkg))
|
||||
}
|
||||
|
||||
/** Gets the `package.json` file in which this path occurs. */
|
||||
PackageJSON getPackageJSON() { result = pkg }
|
||||
PackageJson getPackageJson() { result = pkg }
|
||||
|
||||
override string getValue() { result = this.(JSONString).getValue() }
|
||||
/** DEPRECATED: Alias for getPackageJson */
|
||||
deprecated PackageJSON getPackageJSON() { result = getPackageJson() }
|
||||
|
||||
override string getValue() { result = this.(JsonString).getValue() }
|
||||
|
||||
override Folder getAdditionalSearchRoot(int priority) {
|
||||
priority = 0 and
|
||||
@@ -188,5 +194,5 @@ private class FilesPath extends PathExpr, @json_string {
|
||||
}
|
||||
|
||||
private module FilesPath {
|
||||
FilesPath of(PackageJSON pkg) { result.getPackageJSON() = pkg }
|
||||
FilesPath of(PackageJson pkg) { result.getPackageJson() = pkg }
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ private import NodeModuleResolutionImpl as NodeModule
|
||||
private DataFlow::Node getAValueExportedByPackage() {
|
||||
// The base case, an export from a named `package.json` file.
|
||||
result =
|
||||
getAnExportFromModule(any(PackageJSON pack | exists(pack.getPackageName())).getMainModule())
|
||||
getAnExportFromModule(any(PackageJson pack | exists(pack.getPackageName())).getMainModule())
|
||||
or
|
||||
// module.exports.bar.baz = result;
|
||||
exists(DataFlow::PropWrite write |
|
||||
@@ -133,7 +133,7 @@ private DataFlow::Node getAValueExportedByPackage() {
|
||||
DataFlow::globalVarRef("define").getACall().getArgument(1) = prev.getALocalUse() and
|
||||
func.getFile() =
|
||||
min(int j, File f |
|
||||
f = NodeModule::resolveMainModule(any(PackageJSON pack | exists(pack.getPackageName())), j)
|
||||
f = NodeModule::resolveMainModule(any(PackageJson pack | exists(pack.getPackageName())), j)
|
||||
|
|
||||
f order by j
|
||||
)
|
||||
|
||||
@@ -212,7 +212,7 @@ private module TypeScriptOutDir {
|
||||
* Gets a folder of TypeScript files that is compiled to JavaScript files in `outdir` relative to a `parent`.
|
||||
*/
|
||||
string getOriginalTypeScriptFolder(string outdir, Folder parent) {
|
||||
exists(JSONObject tsconfig |
|
||||
exists(JsonObject tsconfig |
|
||||
outdir = removeLeadingSlash(getOutDir(tsconfig, parent)) and
|
||||
result = removeLeadingSlash(getEffectiveRootDirFromTSConfig(tsconfig))
|
||||
)
|
||||
@@ -229,7 +229,7 @@ private module TypeScriptOutDir {
|
||||
/**
|
||||
* Gets the `outDir` option from a tsconfig file from the folder `parent`.
|
||||
*/
|
||||
private string getOutDir(JSONObject tsconfig, Folder parent) {
|
||||
private string getOutDir(JsonObject tsconfig, Folder parent) {
|
||||
tsconfig.getFile().getBaseName().regexpMatch("tsconfig.*\\.json") and
|
||||
tsconfig.isTopLevel() and
|
||||
tsconfig.getFile().getParentContainer() = parent and
|
||||
@@ -241,7 +241,7 @@ private module TypeScriptOutDir {
|
||||
* Based on the tsconfig.json file `tsconfig`.
|
||||
*/
|
||||
pragma[inline]
|
||||
private string getEffectiveRootDirFromTSConfig(JSONObject tsconfig) {
|
||||
private string getEffectiveRootDirFromTSConfig(JsonObject tsconfig) {
|
||||
// if an explicit "rootDir" option exists, then use that.
|
||||
result = getRootDir(tsconfig)
|
||||
or
|
||||
@@ -273,7 +273,7 @@ private module TypeScriptOutDir {
|
||||
* Can have multiple results if the includes are from multiple folders.
|
||||
*/
|
||||
pragma[inline]
|
||||
private string getARootDirFromInclude(JSONObject tsconfig) {
|
||||
private string getARootDirFromInclude(JsonObject tsconfig) {
|
||||
result =
|
||||
getRootFolderFromPath(tsconfig.getPropValue("include").getElementValue(_).getStringValue())
|
||||
}
|
||||
@@ -282,7 +282,7 @@ private module TypeScriptOutDir {
|
||||
* Gets the value of the "rootDir" option from a tsconfig.json.
|
||||
*/
|
||||
pragma[inline]
|
||||
private string getRootDir(JSONObject tsconfig) {
|
||||
private string getRootDir(JsonObject tsconfig) {
|
||||
result = tsconfig.getPropValue("compilerOptions").getPropValue("rootDir").getStringValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,26 +54,26 @@ private string getQlClass(Locatable el) {
|
||||
*/
|
||||
private newtype TPrintAstNode =
|
||||
// JavaScript / TypeScript
|
||||
TElementNode(ASTNode el) { shouldPrint(el, _) and not isNotNeeded(el) } or
|
||||
TElementNode(AstNode el) { shouldPrint(el, _) and not isNotNeeded(el) } or
|
||||
TParametersNode(Function f) { shouldPrint(f, _) and not isNotNeeded(f) } or
|
||||
TTypeParametersNode(TypeParameterized f) { shouldPrint(f, _) and not isNotNeeded(f) } or
|
||||
TJSXAttributesNode(JSXElement n) { shouldPrint(n, _) and not isNotNeeded(n) } or
|
||||
TJSXBodyElementsNode(JSXNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or
|
||||
TJsxAttributesNode(JsxElement n) { shouldPrint(n, _) and not isNotNeeded(n) } or
|
||||
TJsxBodyElementsNode(JsxNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or
|
||||
TInvokeArgumentsNode(InvokeExpr n) { shouldPrint(n, _) and not isNotNeeded(n) } or
|
||||
TInvokeTypeArgumentsNode(InvokeExpr invk) { shouldPrint(invk, _) and not isNotNeeded(invk) } or
|
||||
// JSON
|
||||
TJSONNode(JSONValue value) { shouldPrint(value, _) and not isNotNeeded(value) } or
|
||||
TJsonNode(JsonValue value) { shouldPrint(value, _) and not isNotNeeded(value) } or
|
||||
// YAML
|
||||
TYAMLNode(YAMLNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or
|
||||
TYAMLMappingNode(YAMLMapping mapping, int i) {
|
||||
TYamlNode(YAMLNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or
|
||||
TYamlMappingNode(YAMLMapping mapping, int i) {
|
||||
shouldPrint(mapping, _) and not isNotNeeded(mapping) and exists(mapping.getKeyNode(i))
|
||||
} or
|
||||
// HTML
|
||||
THTMLElementNode(HTML::Element e) { shouldPrint(e, _) and not isNotNeeded(e) } or
|
||||
THTMLAttributesNodes(HTML::Element e) { shouldPrint(e, _) and not isNotNeeded(e) } or
|
||||
THTMLAttributeNode(HTML::Attribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
|
||||
THTMLScript(Script script) { shouldPrint(script, _) and not isNotNeeded(script) } or
|
||||
THTMLCodeInAttr(CodeInAttribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
|
||||
THtmlElementNode(HTML::Element e) { shouldPrint(e, _) and not isNotNeeded(e) } or
|
||||
THtmlAttributesNodes(HTML::Element e) { shouldPrint(e, _) and not isNotNeeded(e) } or
|
||||
THtmlAttributeNode(HTML::Attribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
|
||||
THtmlScript(Script script) { shouldPrint(script, _) and not isNotNeeded(script) } or
|
||||
THtmlCodeInAttr(CodeInAttribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
|
||||
TRegExpTermNode(RegExpTerm term) {
|
||||
shouldPrint(term, _) and
|
||||
term.isUsedAsRegExp() and
|
||||
@@ -168,7 +168,7 @@ private module PrintJavaScript {
|
||||
* For example by aggregating all the parameters of a function under a single child node.
|
||||
*/
|
||||
class ElementNode extends PrintAstNode, TElementNode {
|
||||
ASTNode element;
|
||||
AstNode element;
|
||||
|
||||
ElementNode() {
|
||||
this = TElementNode(element) and
|
||||
@@ -183,10 +183,10 @@ private module PrintJavaScript {
|
||||
/**
|
||||
* Gets the `ASTNode` represented by this node.
|
||||
*/
|
||||
final ASTNode getElement() { result = element }
|
||||
final AstNode getElement() { result = element }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(ASTNode el | result.(ElementNode).getElement() = el |
|
||||
exists(AstNode el | result.(ElementNode).getElement() = el |
|
||||
el = this.getChildNode(childIndex)
|
||||
)
|
||||
}
|
||||
@@ -195,16 +195,16 @@ private module PrintJavaScript {
|
||||
* Gets the `i`th child of `element`.
|
||||
* Can be overriden in subclasses to get more specific behavior for `getChild()`.
|
||||
*/
|
||||
ASTNode getChildNode(int childIndex) { result = getLocationSortedChild(element, childIndex) }
|
||||
AstNode getChildNode(int childIndex) { result = getLocationSortedChild(element, childIndex) }
|
||||
}
|
||||
|
||||
/** Provides predicates for pretty printing `ASTNode`s. */
|
||||
/** Provides predicates for pretty printing `AstNode`s. */
|
||||
private module PrettyPrinting {
|
||||
/**
|
||||
* Gets a pretty string representation of `element`.
|
||||
* Either the result is `ASTNode::toString`, or a custom made string representation of `element`.
|
||||
*/
|
||||
string print(ASTNode element) {
|
||||
string print(AstNode element) {
|
||||
shouldPrint(element, _) and
|
||||
(
|
||||
result = element.toString().regexpReplaceAll("(\\\\n|\\\\r|\\\\t| )+", " ") and
|
||||
@@ -217,7 +217,7 @@ private module PrintJavaScript {
|
||||
/**
|
||||
* Gets a string representing `a`.
|
||||
*/
|
||||
private string repr(ASTNode a) {
|
||||
private string repr(AstNode a) {
|
||||
shouldPrint(a, _) and
|
||||
(
|
||||
exists(DeclStmt decl | decl = a |
|
||||
@@ -252,9 +252,9 @@ private module PrintJavaScript {
|
||||
}
|
||||
}
|
||||
|
||||
private ASTNode getLocationSortedChild(ASTNode parent, int i) {
|
||||
private AstNode getLocationSortedChild(AstNode parent, int i) {
|
||||
result =
|
||||
rank[i](ASTNode child, int childIndex |
|
||||
rank[i](AstNode child, int childIndex |
|
||||
child = parent.getChild(childIndex)
|
||||
|
|
||||
child
|
||||
@@ -370,62 +370,77 @@ private module PrintJavaScript {
|
||||
* 2: An aggregate node for all the attributes (for example `href={foo}` in `<Name href={foo} />`).
|
||||
* 3: An aggregate node for all the body element (for example `foo` in `<span>foo</span>`).
|
||||
*/
|
||||
class JSXNodeNode extends ElementNode {
|
||||
override JSXNode element;
|
||||
class JsxNodeNode extends ElementNode {
|
||||
override JsxNode element;
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
childIndex = 0 and result.(ElementNode).getElement() = element.(JSXElement).getNameExpr()
|
||||
childIndex = 0 and result.(ElementNode).getElement() = element.(JsxElement).getNameExpr()
|
||||
or
|
||||
childIndex = 1 and
|
||||
exists(element.getABodyElement()) and
|
||||
result.(JSXBodyElementsNode).getJSXNode() = element
|
||||
result.(JsxBodyElementsNode).getJsxNode() = element
|
||||
or
|
||||
childIndex = 2 and
|
||||
exists(element.(JSXElement).getAttribute(_)) and
|
||||
result.(JSXAttributesNode).getJSXElement() = element
|
||||
exists(element.(JsxElement).getAttribute(_)) and
|
||||
result.(JsxAttributesNode).getJsxElement() = element
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxNodeNode */
|
||||
deprecated class JSXNodeNode = JsxNodeNode;
|
||||
|
||||
/**
|
||||
* An aggregate node representing all the attributes in a `JSXNode`.
|
||||
*/
|
||||
class JSXAttributesNode extends PrintAstNode, TJSXAttributesNode {
|
||||
JSXElement n;
|
||||
class JsxAttributesNode extends PrintAstNode, TJsxAttributesNode {
|
||||
JsxElement n;
|
||||
|
||||
JSXAttributesNode() { this = TJSXAttributesNode(n) and exists(n.getAttribute(_)) }
|
||||
JsxAttributesNode() { this = TJsxAttributesNode(n) and exists(n.getAttribute(_)) }
|
||||
|
||||
override string toString() { result = "(Attributes)" }
|
||||
|
||||
/**
|
||||
* Gets the `JSXElement` for which this node represents the attributes.
|
||||
*/
|
||||
JSXElement getJSXElement() { result = n }
|
||||
JsxElement getJsxElement() { result = n }
|
||||
|
||||
/** DEPRECATED: Alias for getJsxElement */
|
||||
deprecated JSXElement getJSXElement() { result = this.getJsxElement() }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
result.(ElementNode).getElement() = n.getAttribute(childIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxAttributesNode */
|
||||
deprecated class JSXAttributesNode = JsxAttributesNode;
|
||||
|
||||
/**
|
||||
* An aggregate node representing all the body elements in a `JSXNode`.
|
||||
*/
|
||||
class JSXBodyElementsNode extends PrintAstNode, TJSXBodyElementsNode {
|
||||
JSXNode n;
|
||||
class JsxBodyElementsNode extends PrintAstNode, TJsxBodyElementsNode {
|
||||
JsxNode n;
|
||||
|
||||
JSXBodyElementsNode() { this = TJSXBodyElementsNode(n) and exists(n.getBodyElement(_)) }
|
||||
JsxBodyElementsNode() { this = TJsxBodyElementsNode(n) and exists(n.getBodyElement(_)) }
|
||||
|
||||
override string toString() { result = "(Body)" }
|
||||
|
||||
/**
|
||||
* Gets the `JSXNode` for which this node represents the body elements.
|
||||
*/
|
||||
JSXNode getJSXNode() { result = n }
|
||||
JsxNode getJsxNode() { result = n }
|
||||
|
||||
/** DEPRECATED: Alias for getJsxNode */
|
||||
deprecated JSXNode getJSXNode() { result = this.getJsxNode() }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
result.(ElementNode).getElement() = n.getBodyElement(childIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxBodyElementsNode */
|
||||
deprecated class JSXBodyElementsNode = JsxBodyElementsNode;
|
||||
|
||||
/**
|
||||
* A node representing any `ASTNode` that has type-parameters.
|
||||
*
|
||||
@@ -484,7 +499,7 @@ private module PrintJavaScript {
|
||||
class ParameterNode extends ElementNode {
|
||||
override Parameter element;
|
||||
|
||||
override ASTNode getChildNode(int childIndex) {
|
||||
override AstNode getChildNode(int childIndex) {
|
||||
childIndex = 0 and result = element.getTypeAnnotation()
|
||||
or
|
||||
childIndex = 1 and result = element.getDefault()
|
||||
@@ -535,14 +550,14 @@ private module PrintJavaScript {
|
||||
/**
|
||||
* Classes for printing JSON AST.
|
||||
*/
|
||||
private module PrintJSON {
|
||||
private module PrintJson {
|
||||
/**
|
||||
* A print node representing a JSON value in a .json file.
|
||||
*/
|
||||
class JSONNode extends PrintAstNode, TJSONNode {
|
||||
JSONValue value;
|
||||
class JsonNode extends PrintAstNode, TJsonNode {
|
||||
JsonValue value;
|
||||
|
||||
JSONNode() { this = TJSONNode(value) }
|
||||
JsonNode() { this = TJsonNode(value) }
|
||||
|
||||
override string toString() { result = getQlClass(value) + PrettyPrinting::print(value) }
|
||||
|
||||
@@ -551,22 +566,25 @@ private module PrintJSON {
|
||||
/**
|
||||
* Gets the `JSONValue` represented by this node.
|
||||
*/
|
||||
final JSONValue getValue() { result = value }
|
||||
final JsonValue getValue() { result = value }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(JSONValue child | result.(JSONNode).getValue() = child |
|
||||
exists(JsonValue child | result.(JsonNode).getValue() = child |
|
||||
child = value.getChild(childIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonNode */
|
||||
deprecated class JSONNode = JsonNode;
|
||||
|
||||
/** Provied predicates for pretty printing JSON. */
|
||||
private module PrettyPrinting {
|
||||
/**
|
||||
* Gets a string representation of `n`.
|
||||
* Either using the default `JSONValue::toString`, or a custom printing of the JSON value.
|
||||
*/
|
||||
string print(JSONValue n) {
|
||||
string print(JsonValue n) {
|
||||
shouldPrint(n, _) and
|
||||
(
|
||||
result = n.toString().regexpReplaceAll("(\\\\n|\\\\r|\\\\t| )+", " ") and
|
||||
@@ -577,20 +595,20 @@ private module PrintJSON {
|
||||
}
|
||||
|
||||
/** Gets a string representing `n`. */
|
||||
private string repr(JSONValue n) {
|
||||
private string repr(JsonValue n) {
|
||||
shouldPrint(n, _) and
|
||||
(
|
||||
exists(JSONObject obj, string name, JSONValue prop | obj = n |
|
||||
exists(JsonObject obj, string name, JsonValue prop | obj = n |
|
||||
prop = obj.getPropValue(name) and
|
||||
prop = obj.getChild(0) and
|
||||
result = "{" + name + ": ...}"
|
||||
)
|
||||
or
|
||||
n instanceof JSONObject and not exists(n.getChild(_)) and result = "{}"
|
||||
n instanceof JsonObject and not exists(n.getChild(_)) and result = "{}"
|
||||
or
|
||||
result = n.(JSONPrimitiveValue).getRawValue()
|
||||
result = n.(JsonPrimitiveValue).getRawValue()
|
||||
or
|
||||
exists(JSONArray arr | arr = n |
|
||||
exists(JsonArray arr | arr = n |
|
||||
result = "[]" and not exists(arr.getChild(_))
|
||||
or
|
||||
result = "[" + repr(arr.getChild(0)) + "]" and not exists(arr.getChild(1))
|
||||
@@ -605,14 +623,14 @@ private module PrintJSON {
|
||||
/**
|
||||
* Classes for printing YAML AST.
|
||||
*/
|
||||
module PrintYAML {
|
||||
module PrintYaml {
|
||||
/**
|
||||
* A print node representing a YAML value in a .yml file.
|
||||
*/
|
||||
class YAMLNodeNode extends PrintAstNode, TYAMLNode {
|
||||
class YamlNodeNode extends PrintAstNode, TYamlNode {
|
||||
YAMLNode node;
|
||||
|
||||
YAMLNodeNode() { this = TYAMLNode(node) }
|
||||
YamlNodeNode() { this = TYamlNode(node) }
|
||||
|
||||
override string toString() { result = getQlClass(node) + node.toString() }
|
||||
|
||||
@@ -624,33 +642,39 @@ module PrintYAML {
|
||||
final YAMLNode getValue() { result = node }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(YAMLNode child | result.(YAMLNodeNode).getValue() = child |
|
||||
exists(YAMLNode child | result.(YamlNodeNode).getValue() = child |
|
||||
child = node.getChildNode(childIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for YamlNodeNode */
|
||||
deprecated class YAMLNodeNode = YamlNodeNode;
|
||||
|
||||
/**
|
||||
* A print node representing a `YAMLMapping`.
|
||||
*
|
||||
* Each child of this node aggregates the key and value of a mapping.
|
||||
*/
|
||||
class YAMLMappingNode extends YAMLNodeNode {
|
||||
class YamlMappingNode extends YamlNodeNode {
|
||||
override YAMLMapping node;
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
exists(YAMLMappingMapNode map | map = result | map.maps(node, childIndex))
|
||||
exists(YamlMappingMapNode map | map = result | map.maps(node, childIndex))
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for YamlMappingNode */
|
||||
deprecated class YAMLMappingNode = YamlMappingNode;
|
||||
|
||||
/**
|
||||
* A print node representing the `i`th mapping in `mapping`.
|
||||
*/
|
||||
class YAMLMappingMapNode extends PrintAstNode, TYAMLMappingNode {
|
||||
class YamlMappingMapNode extends PrintAstNode, TYamlMappingNode {
|
||||
YAMLMapping mapping;
|
||||
int i;
|
||||
|
||||
YAMLMappingMapNode() { this = TYAMLMappingNode(mapping, i) }
|
||||
YamlMappingMapNode() { this = TYamlMappingNode(mapping, i) }
|
||||
|
||||
override string toString() {
|
||||
result = "(Mapping " + i + ")" and not exists(mapping.getKeyNode(i).(YAMLScalar).getValue())
|
||||
@@ -667,24 +691,30 @@ module PrintYAML {
|
||||
}
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
childIndex = 0 and result.(YAMLNodeNode).getValue() = mapping.getKeyNode(i)
|
||||
childIndex = 0 and result.(YamlNodeNode).getValue() = mapping.getKeyNode(i)
|
||||
or
|
||||
childIndex = 1 and result.(YAMLNodeNode).getValue() = mapping.getValueNode(i)
|
||||
childIndex = 1 and result.(YamlNodeNode).getValue() = mapping.getValueNode(i)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for YamlMappingMapNode */
|
||||
deprecated class YAMLMappingMapNode = YamlMappingMapNode;
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PrintYaml */
|
||||
deprecated module PrintYAML = PrintYaml;
|
||||
|
||||
/**
|
||||
* Classes for printing HTML AST.
|
||||
*/
|
||||
module PrintHTML {
|
||||
module PrintHtml {
|
||||
/**
|
||||
* A print node representing an HTML node in a .html file.
|
||||
*/
|
||||
class HTMLElementNode extends PrintAstNode, THTMLElementNode {
|
||||
class HtmlElementNode extends PrintAstNode, THtmlElementNode {
|
||||
HTML::Element element;
|
||||
|
||||
HTMLElementNode() { this = THTMLElementNode(element) }
|
||||
HtmlElementNode() { this = THtmlElementNode(element) }
|
||||
|
||||
override string toString() { result = getQlClass(element) + "<" + element.getName() + " ..." }
|
||||
|
||||
@@ -696,36 +726,42 @@ module PrintHTML {
|
||||
final HTML::Element getElement() { result = element }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
childIndex = -1 and result.(HTMLAttributesNodes).getElement() = element
|
||||
childIndex = -1 and result.(HtmlAttributesNodes).getElement() = element
|
||||
or
|
||||
exists(HTML::Element child | result.(HTMLElementNode).getElement() = child |
|
||||
exists(HTML::Element child | result.(HtmlElementNode).getElement() = child |
|
||||
child = element.getChild(childIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for HtmlElementNode */
|
||||
deprecated class HTMLElementNode = HtmlElementNode;
|
||||
|
||||
/**
|
||||
* A print node representing an HTML node in a .html file.
|
||||
*/
|
||||
class HTMLScriptElementNode extends HTMLElementNode {
|
||||
class HtmlScriptElementNode extends HtmlElementNode {
|
||||
override HTML::ScriptElement element;
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
childIndex = -200 and result.(HTMLScript).getScript() = element.getScript()
|
||||
childIndex = -200 and result.(HtmlScript).getScript() = element.getScript()
|
||||
or
|
||||
result = super.getChild(childIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for HtmlScriptElementNode */
|
||||
deprecated class HTMLScriptElementNode = HtmlScriptElementNode;
|
||||
|
||||
/**
|
||||
* A print node representing the code inside a `<script>` element.
|
||||
*/
|
||||
class HTMLScript extends PrintAstNode, THTMLScript {
|
||||
class HtmlScript extends PrintAstNode, THtmlScript {
|
||||
Script script;
|
||||
|
||||
HTMLScript() {
|
||||
this = THTMLScript(script) and
|
||||
any(HTMLScriptElementNode se).getElement().(HTML::ScriptElement).getScript() = script
|
||||
HtmlScript() {
|
||||
this = THtmlScript(script) and
|
||||
any(HtmlScriptElementNode se).getElement().(HTML::ScriptElement).getScript() = script
|
||||
}
|
||||
|
||||
override string toString() { result = "(Script)" }
|
||||
@@ -742,15 +778,18 @@ module PrintHTML {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for HtmlScript */
|
||||
deprecated class HTMLScript = HtmlScript;
|
||||
|
||||
/**
|
||||
* A print node representing the code inside an attribute.
|
||||
*/
|
||||
class HTMLCodeInAttr extends PrintAstNode, THTMLCodeInAttr {
|
||||
class HtmlCodeInAttr extends PrintAstNode, THtmlCodeInAttr {
|
||||
CodeInAttribute attr;
|
||||
|
||||
HTMLCodeInAttr() {
|
||||
this = THTMLCodeInAttr(attr) and
|
||||
any(HTMLAttributeNode an).getAttribute().getCodeInAttribute() = attr
|
||||
HtmlCodeInAttr() {
|
||||
this = THtmlCodeInAttr(attr) and
|
||||
any(HtmlAttributeNode an).getAttribute().getCodeInAttribute() = attr
|
||||
}
|
||||
|
||||
override string toString() { result = "(Script)" }
|
||||
@@ -767,14 +806,17 @@ module PrintHTML {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for HtmlCodeInAttr */
|
||||
deprecated class HTMLCodeInAttr = HtmlCodeInAttr;
|
||||
|
||||
/**
|
||||
* An aggregate node representing all the attributes of an HTMLElement.
|
||||
*/
|
||||
class HTMLAttributesNodes extends PrintAstNode, THTMLAttributesNodes {
|
||||
class HtmlAttributesNodes extends PrintAstNode, THtmlAttributesNodes {
|
||||
HTML::Element element;
|
||||
|
||||
HTMLAttributesNodes() {
|
||||
this = THTMLAttributesNodes(element) and exists(element.getAttribute(_))
|
||||
HtmlAttributesNodes() {
|
||||
this = THtmlAttributesNodes(element) and exists(element.getAttribute(_))
|
||||
}
|
||||
|
||||
override string toString() { result = "(Attributes)" }
|
||||
@@ -785,17 +827,20 @@ module PrintHTML {
|
||||
HTML::Element getElement() { result = element }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
result.(HTMLAttributeNode).getAttribute() = element.getAttribute(childIndex)
|
||||
result.(HtmlAttributeNode).getAttribute() = element.getAttribute(childIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for HtmlAttributesNodes */
|
||||
deprecated class HTMLAttributesNodes = HtmlAttributesNodes;
|
||||
|
||||
/**
|
||||
* A print node representing an HTML attribute in a .html file.
|
||||
*/
|
||||
class HTMLAttributeNode extends PrintAstNode, THTMLAttributeNode {
|
||||
class HtmlAttributeNode extends PrintAstNode, THtmlAttributeNode {
|
||||
HTML::Attribute attr;
|
||||
|
||||
HTMLAttributeNode() { this = THTMLAttributeNode(attr) }
|
||||
HtmlAttributeNode() { this = THtmlAttributeNode(attr) }
|
||||
|
||||
override string toString() { result = getQlClass(attr) + attr.toString() }
|
||||
|
||||
@@ -807,11 +852,17 @@ module PrintHTML {
|
||||
final HTML::Attribute getAttribute() { result = attr }
|
||||
|
||||
override PrintAstNode getChild(int childIndex) {
|
||||
childIndex = 0 and result.(HTMLCodeInAttr).getCode() = attr.getCodeInAttribute()
|
||||
childIndex = 0 and result.(HtmlCodeInAttr).getCode() = attr.getCodeInAttribute()
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for HtmlAttributeNode */
|
||||
deprecated class HTMLAttributeNode = HtmlAttributeNode;
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PrintHtml */
|
||||
deprecated module PrintHTML = PrintHtml;
|
||||
|
||||
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
|
||||
query predicate nodes(PrintAstNode node, string key, string value) { value = node.getProperty(key) }
|
||||
|
||||
|
||||
@@ -434,11 +434,6 @@ module PromiseFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `TaintTracking::promiseStep` instead.
|
||||
*/
|
||||
deprecated predicate promiseTaintStep = TaintTracking::promiseStep/2;
|
||||
|
||||
private class PromiseTaintStep extends TaintTracking::SharedTaintStep {
|
||||
override predicate promiseStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
// from `x` to `new Promise((res, rej) => res(x))`
|
||||
|
||||
@@ -663,15 +663,6 @@ class RegExpNormalConstant extends RegExpConstant, @regexp_normal_constant {
|
||||
override string getAPrimaryQlClass() { result = "RegExpNormalConstant" }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use `RegExpNormalConstant` instead.
|
||||
*
|
||||
* This class used to represent an individual normal character but has been superseded by
|
||||
* `RegExpNormalConstant`, which represents a sequence of normal characters.
|
||||
* There is no longer a separate node for each individual character in a constant.
|
||||
*/
|
||||
deprecated class RegExpNormalChar = RegExpNormalConstant;
|
||||
|
||||
/**
|
||||
* A hexadecimal character escape in a regular expression.
|
||||
*
|
||||
@@ -1306,8 +1297,8 @@ module RegExp {
|
||||
/**
|
||||
* A meta character used by HTML.
|
||||
*/
|
||||
private class HTMLMetaCharacter extends MetaCharacter {
|
||||
HTMLMetaCharacter() { this = ["<", "'", "\""] }
|
||||
private class HtmlMetaCharacter extends MetaCharacter {
|
||||
HtmlMetaCharacter() { this = ["<", "'", "\""] }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,17 +10,20 @@ class SourceMappingComment extends Comment {
|
||||
string url;
|
||||
|
||||
SourceMappingComment() {
|
||||
exists(string sourceMappingURLRegex |
|
||||
sourceMappingURLRegex = "[@#]\\s*sourceMappingURL\\s*=\\s*(.*)\\s*"
|
||||
exists(string sourceMappingUrlRegex |
|
||||
sourceMappingUrlRegex = "[@#]\\s*sourceMappingURL\\s*=\\s*(.*)\\s*"
|
||||
|
|
||||
// either a line comment whose entire text matches the regex...
|
||||
url = this.(SlashSlashComment).getText().regexpCapture(sourceMappingURLRegex, 1)
|
||||
url = this.(SlashSlashComment).getText().regexpCapture(sourceMappingUrlRegex, 1)
|
||||
or
|
||||
// ...or a block comment one of whose lines matches the regex
|
||||
url = this.(SlashStarComment).getLine(_).regexpCapture("//" + sourceMappingURLRegex, 1)
|
||||
url = this.(SlashStarComment).getLine(_).regexpCapture("//" + sourceMappingUrlRegex, 1)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the URL of the source map referenced by this comment. */
|
||||
string getSourceMappingURL() { result = url }
|
||||
string getSourceMappingUrl() { result = url }
|
||||
|
||||
/** DEPRECATED: Alias for getSourceMappingUrl */
|
||||
deprecated string getSourceMappingURL() { result = getSourceMappingUrl() }
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ private class MaybeDirective extends ExprStmt {
|
||||
*/
|
||||
class Directive extends MaybeDirective {
|
||||
Directive() {
|
||||
exists(StmtContainer sc, ASTNode body, int i |
|
||||
exists(StmtContainer sc, AstNode body, int i |
|
||||
// directives must be toplevel statements in their container
|
||||
body = sc.getBody() and
|
||||
this = body.getChildStmt(i) and
|
||||
@@ -502,7 +502,7 @@ class JumpStmt extends TJumpStmt, Stmt {
|
||||
* Note that this predicate does not take `finally` clauses
|
||||
* into account, which may interrupt the jump.
|
||||
*/
|
||||
abstract ASTNode getTarget();
|
||||
abstract AstNode getTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -583,7 +583,7 @@ class WithStmt extends @with_stmt, ControlStmt {
|
||||
exists(Variable v | v = acc.getVariable() |
|
||||
v instanceof GlobalVariable
|
||||
or
|
||||
exists(ASTNode scopeElt | scopeElt = v.getScope().getScopeElement() |
|
||||
exists(AstNode scopeElt | scopeElt = v.getScope().getScopeElement() |
|
||||
scopeElt = this.getParent+()
|
||||
)
|
||||
)
|
||||
@@ -676,7 +676,7 @@ class ThrowStmt extends @throw_stmt, JumpStmt {
|
||||
* `try` statement in whose body the throw statement occurs. If there is no such
|
||||
* `try` statement, the target defaults to the enclosing statement container.
|
||||
*/
|
||||
override ASTNode getTarget() {
|
||||
override AstNode getTarget() {
|
||||
if exists(TryStmt ts | this.getParentStmt+() = ts.getBody())
|
||||
then
|
||||
this.getParentStmt+() = result.(TryStmt).getBody() and
|
||||
@@ -802,7 +802,7 @@ class DoWhileStmt extends @do_while_stmt, LoopStmt {
|
||||
* var i = 1;
|
||||
* ```
|
||||
*/
|
||||
class ExprOrVarDecl extends ASTNode {
|
||||
class ExprOrVarDecl extends AstNode {
|
||||
ExprOrVarDecl() {
|
||||
this instanceof Expr or
|
||||
this instanceof DeclStmt
|
||||
|
||||
@@ -98,7 +98,7 @@ class NamespaceDeclaration extends NamespaceDefinition, StmtContainer, @namespac
|
||||
* Note that imports and type parameters are not type definitions. Consider using `TypeDecl` to capture
|
||||
* a wider class of type declarations.
|
||||
*/
|
||||
class TypeDefinition extends ASTNode, @type_definition {
|
||||
class TypeDefinition extends AstNode, @type_definition {
|
||||
/**
|
||||
* Gets the identifier naming the type.
|
||||
*/
|
||||
@@ -376,7 +376,7 @@ class ConstructorTypeExpr extends FunctionTypeExpr, @constructor_typeexpr { }
|
||||
class PlainFunctionTypeExpr extends FunctionTypeExpr, @plain_function_typeexpr { }
|
||||
|
||||
/** A possibly qualified identifier that declares or refers to a type. */
|
||||
abstract class TypeRef extends ASTNode { }
|
||||
abstract class TypeRef extends AstNode { }
|
||||
|
||||
/** An identifier declaring a type name, that is, the name of a class, interface, type parameter, or import. */
|
||||
class TypeDecl extends Identifier, TypeRef, LexicalDecl {
|
||||
@@ -1291,7 +1291,7 @@ class ExpressionWithTypeArguments extends @expression_with_type_arguments, Expr
|
||||
/**
|
||||
* A program element that supports type parameters, that is, a function, class, interface, type alias, mapped type, or `infer` type.
|
||||
*/
|
||||
class TypeParameterized extends @type_parameterized, ASTNode {
|
||||
class TypeParameterized extends @type_parameterized, AstNode {
|
||||
/** Gets the `n`th type parameter declared on this function or type. */
|
||||
TypeParameter getTypeParameter(int n) { none() } // Overridden in subtypes.
|
||||
|
||||
@@ -1394,7 +1394,7 @@ class NonNullAssertion extends Expr, @non_null_assertion {
|
||||
/**
|
||||
* A possibly qualified identifier that refers to or declares a local name for a namespace.
|
||||
*/
|
||||
abstract class NamespaceRef extends ASTNode { }
|
||||
abstract class NamespaceRef extends AstNode { }
|
||||
|
||||
/**
|
||||
* An identifier that declares a local name for a namespace, that is,
|
||||
@@ -1602,7 +1602,7 @@ class EnumDeclaration extends NamespaceDefinition, @enum_declaration, AST::Value
|
||||
* enum Color { red = 1, green, blue }
|
||||
* ```
|
||||
*/
|
||||
class EnumMember extends ASTNode, @enum_member {
|
||||
class EnumMember extends AstNode, @enum_member {
|
||||
/**
|
||||
* Gets the name of the enum member, such as `off` in `enum State { on, off }`.
|
||||
*
|
||||
@@ -1754,20 +1754,6 @@ class ReferenceImport extends LineComment {
|
||||
* Gets the name of the attribute, i.e. "`path`" or "`types`".
|
||||
*/
|
||||
string getAttributeName() { result = attribute }
|
||||
|
||||
/**
|
||||
* DEPRECATED. This is no longer supported.
|
||||
*
|
||||
* Gets the file referenced by this import.
|
||||
*/
|
||||
deprecated File getImportedFile() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED. This is no longer supported.
|
||||
*
|
||||
* Gets the top-level of the referenced file.
|
||||
*/
|
||||
deprecated TopLevel getImportedTopLevel() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1853,11 +1839,6 @@ class Type extends @type {
|
||||
*/
|
||||
Type getChild(int i) { type_child(result, this, i) }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Property lookup on types is no longer supported.
|
||||
*/
|
||||
deprecated Type getProperty(string name) { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the string index signature on this type,
|
||||
* such as `T` in the type `{ [s: string]: T }`.
|
||||
@@ -1960,21 +1941,6 @@ class Type extends @type {
|
||||
*/
|
||||
int getNumConstructorSignature() { result = count(this.getAConstructorSignature()) }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Method lookup on types is no longer supported.
|
||||
*/
|
||||
deprecated FunctionCallSignatureType getMethod(string name) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Method lookup on types is no longer supported.
|
||||
*/
|
||||
deprecated FunctionCallSignatureType getMethodOverload(string name, int n) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Method lookup on types is no longer supported.
|
||||
*/
|
||||
deprecated FunctionCallSignatureType getAMethodOverload(string name) { none() }
|
||||
|
||||
/**
|
||||
* Repeatedly unfolds union and intersection types and gets any of the underlying types,
|
||||
* or this type itself if it is not a union or intersection.
|
||||
|
||||
@@ -14,7 +14,7 @@ class Scope extends @scope {
|
||||
Scope getAnInnerScope() { result.getOuterScope() = this }
|
||||
|
||||
/** Gets the program element this scope is associated with, if any. */
|
||||
ASTNode getScopeElement() { scopenodes(result, this) }
|
||||
AstNode getScopeElement() { scopenodes(result, this) }
|
||||
|
||||
/** Gets the location of the program element this scope is associated with, if any. */
|
||||
Location getLocation() { result = this.getScopeElement().getLocation() }
|
||||
@@ -32,7 +32,7 @@ class Scope extends @scope {
|
||||
/**
|
||||
* A program element that induces a scope.
|
||||
*/
|
||||
class ScopeElement extends ASTNode {
|
||||
class ScopeElement extends AstNode {
|
||||
Scope s;
|
||||
|
||||
ScopeElement() { this = s.getScopeElement() }
|
||||
@@ -581,7 +581,7 @@ class ObjectPattern extends DestructuringPattern, @object_pattern {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class PropertyPattern extends @property, ASTNode {
|
||||
class PropertyPattern extends @property, AstNode {
|
||||
PropertyPattern() {
|
||||
// filter out ordinary properties
|
||||
exists(ObjectPattern obj | properties(this, obj, _, _, _))
|
||||
|
||||
@@ -4,21 +4,14 @@
|
||||
|
||||
import semmle.files.FileSystem
|
||||
|
||||
private class TXMLLocatable =
|
||||
private class TXmlLocatable =
|
||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
class XMLLocatable extends @xmllocatable, TXMLLocatable {
|
||||
class XMLLocatable extends @xmllocatable, TXmlLocatable {
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLocation()` instead.
|
||||
*
|
||||
* Gets the source location for this element.
|
||||
*/
|
||||
deprecated Location getALocation() { result = this.getLocation() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
@@ -83,21 +76,6 @@ class XMLParent extends @xmlparent {
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Internal.
|
||||
*
|
||||
* Append the character sequences of this XML parent from left to right, separated by a space,
|
||||
* up to a specified (zero-based) index.
|
||||
*/
|
||||
deprecated string charsSetUpTo(int n) {
|
||||
n = 0 and xmlChars(_, result, this, 0, _, _)
|
||||
or
|
||||
n > 0 and
|
||||
exists(string chars | xmlChars(_, chars, this, n, _, _) |
|
||||
result = this.charsSetUpTo(n - 1) + " " + chars
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
|
||||
@@ -166,20 +166,6 @@ abstract class Configuration extends string {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrierEdge` instead.
|
||||
*
|
||||
* Holds if flow from `src` to `trg` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrier(DataFlow::Node src, DataFlow::Node trg) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrierEdge` instead.
|
||||
*
|
||||
* Holds if flow with label `lbl` cannot flow from `src` to `trg`.
|
||||
*/
|
||||
deprecated predicate isBarrier(DataFlow::Node src, DataFlow::Node trg, FlowLabel lbl) { none() }
|
||||
|
||||
/**
|
||||
* Holds if flow from `pred` to `succ` is prohibited.
|
||||
*/
|
||||
@@ -535,13 +521,6 @@ private predicate isLabeledBarrierEdge(
|
||||
*/
|
||||
abstract class LabeledBarrierGuardNode extends BarrierGuardNode {
|
||||
override predicate blocks(boolean outcome, Expr e) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `blocks(outcome, e, label)` or `sanitizes(outcome, e, label)` instead.
|
||||
*
|
||||
* Overriding this predicate has no effect.
|
||||
*/
|
||||
deprecated FlowLabel getALabel() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,7 +78,7 @@ module DataFlow {
|
||||
}
|
||||
|
||||
/** Gets the AST node corresponding to this data flow node, if any. */
|
||||
ASTNode getAstNode() { none() }
|
||||
AstNode getAstNode() { none() }
|
||||
|
||||
/** Gets the basic block to which this node belongs. */
|
||||
BasicBlock getBasicBlock() { none() }
|
||||
@@ -332,7 +332,7 @@ module DataFlow {
|
||||
|
||||
override File getFile() { result = ssa.getBasicBlock().getFile() }
|
||||
|
||||
override ASTNode getAstNode() { none() }
|
||||
override AstNode getAstNode() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,11 +353,11 @@ module DataFlow {
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
override string toString() { result = prop.(ASTNode).toString() }
|
||||
override string toString() { result = prop.(AstNode).toString() }
|
||||
|
||||
override File getFile() { result = prop.(ASTNode).getFile() }
|
||||
override File getFile() { result = prop.(AstNode).getFile() }
|
||||
|
||||
override ASTNode getAstNode() { result = prop }
|
||||
override AstNode getAstNode() { result = prop }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,7 +382,7 @@ module DataFlow {
|
||||
|
||||
override File getFile() { result = pattern.getFile() }
|
||||
|
||||
override ASTNode getAstNode() { result = rest }
|
||||
override AstNode getAstNode() { result = rest }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -407,7 +407,7 @@ module DataFlow {
|
||||
|
||||
override File getFile() { result = pattern.getFile() }
|
||||
|
||||
override ASTNode getAstNode() { result = elt }
|
||||
override AstNode getAstNode() { result = elt }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +436,7 @@ module DataFlow {
|
||||
|
||||
override File getFile() { result = arr.getFile() }
|
||||
|
||||
override ASTNode getAstNode() { result = elt }
|
||||
override AstNode getAstNode() { result = elt }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,9 +445,8 @@ module DataFlow {
|
||||
*/
|
||||
private class ReflectiveCallNode extends Node, TReflectiveCallNode {
|
||||
MethodCallExpr call;
|
||||
string kind;
|
||||
|
||||
ReflectiveCallNode() { this = TReflectiveCallNode(call, kind) }
|
||||
ReflectiveCallNode() { this = TReflectiveCallNode(call, _) }
|
||||
|
||||
override BasicBlock getBasicBlock() { result = call.getBasicBlock() }
|
||||
|
||||
@@ -720,7 +719,7 @@ module DataFlow {
|
||||
* the JSX element it is in.
|
||||
*/
|
||||
private class JsxAttributeAsPropWrite extends PropWrite, PropNode {
|
||||
override JSXAttribute prop;
|
||||
override JsxAttribute prop;
|
||||
|
||||
override Node getBase() { result = valueNode(prop.getElement()) }
|
||||
|
||||
@@ -1308,7 +1307,7 @@ module DataFlow {
|
||||
* This predicate is only defined for expressions, properties, and for statements that declare
|
||||
* a function, a class, or a TypeScript namespace or enum.
|
||||
*/
|
||||
ValueNode valueNode(ASTNode nd) { result.getAstNode() = nd }
|
||||
ValueNode valueNode(AstNode nd) { result.getAstNode() = nd }
|
||||
|
||||
/**
|
||||
* Gets the data flow node corresponding to `e`.
|
||||
@@ -1670,11 +1669,11 @@ module DataFlow {
|
||||
or
|
||||
exists(Expr e | e = nd.asExpr() and cause = "heap" |
|
||||
e instanceof PropAccess or
|
||||
e instanceof E4X::XMLAnyName or
|
||||
e instanceof E4X::XMLAttributeSelector or
|
||||
e instanceof E4X::XMLDotDotExpression or
|
||||
e instanceof E4X::XMLFilterExpression or
|
||||
e instanceof E4X::XMLQualifiedIdentifier or
|
||||
e instanceof E4X::XmlAnyName or
|
||||
e instanceof E4X::XmlAttributeSelector or
|
||||
e instanceof E4X::XmlDotDotExpression or
|
||||
e instanceof E4X::XmlFilterExpression or
|
||||
e instanceof E4X::XmlQualifiedIdentifier or
|
||||
e instanceof Angular2::PipeRefExpr
|
||||
)
|
||||
or
|
||||
@@ -1716,9 +1715,8 @@ module DataFlow {
|
||||
import Sources
|
||||
import TypeInference
|
||||
import Configuration
|
||||
import TrackedNodes
|
||||
import TypeTracking
|
||||
import internal.FunctionWrapperSteps
|
||||
|
||||
predicate localTaintStep = TaintTracking::localTaintStep/2;
|
||||
deprecated predicate localTaintStep = TaintTracking::localTaintStep/2;
|
||||
}
|
||||
|
||||
@@ -1403,13 +1403,6 @@ module PartialInvokeNode {
|
||||
*/
|
||||
DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use the one-argument version of `getBoundReceiver` instead.
|
||||
*
|
||||
* Gets the node holding the receiver to be passed to the bound function, if specified.
|
||||
*/
|
||||
deprecated DataFlow::Node getBoundReceiver() { none() }
|
||||
|
||||
/**
|
||||
* Gets the node holding the receiver to be passed to `callback`.
|
||||
*/
|
||||
@@ -1541,16 +1534,6 @@ module PartialInvokeNode {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Subclasses should extend `PartialInvokeNode::Range` instead,
|
||||
* and predicates should use `PartialInvokeNode` instead.
|
||||
*
|
||||
* An invocation that is modeled as a partial function application.
|
||||
*
|
||||
* This contributes additional argument-passing flow edges that should be added to all data flow configurations.
|
||||
*/
|
||||
deprecated class AdditionalPartialInvokeNode = PartialInvokeNode::Range;
|
||||
|
||||
/**
|
||||
* An invocation of the `RegExp` constructor.
|
||||
*
|
||||
|
||||
@@ -180,7 +180,7 @@ private class NpmPackagePortal extends Portal, MkNpmPackagePortal {
|
||||
private module NpmPackagePortal {
|
||||
/** Gets an import of `imported` inside package `importer`. */
|
||||
pragma[noinline]
|
||||
private DataFlow::SourceNode getAModuleImport(NPMPackage importer, string imported) {
|
||||
private DataFlow::SourceNode getAModuleImport(NpmPackage importer, string imported) {
|
||||
result = DataFlow::moduleImport(imported) and
|
||||
result.getTopLevel() = importer.getAModule()
|
||||
}
|
||||
@@ -188,7 +188,7 @@ private module NpmPackagePortal {
|
||||
/** Gets an import of `member` from `imported` inside package `importer`. */
|
||||
pragma[noinline]
|
||||
private DataFlow::SourceNode getAModuleMemberImport(
|
||||
NPMPackage importer, string imported, string member
|
||||
NpmPackage importer, string imported, string member
|
||||
) {
|
||||
result = DataFlow::moduleMember(imported, member) and
|
||||
result.getTopLevel() = importer.getAModule()
|
||||
@@ -196,7 +196,7 @@ private module NpmPackagePortal {
|
||||
|
||||
/** Holds if `imp` is an import of package `pkgName`. */
|
||||
predicate imports(DataFlow::SourceNode imp, string pkgName) {
|
||||
exists(NPMPackage pkg |
|
||||
exists(NpmPackage pkg |
|
||||
imp = getAModuleImport(pkg, pkgName) and
|
||||
pkgName.regexpMatch("[^./].*")
|
||||
)
|
||||
@@ -204,7 +204,7 @@ private module NpmPackagePortal {
|
||||
|
||||
/** Holds if `imp` imports `member` from package `pkgName`. */
|
||||
predicate imports(DataFlow::SourceNode imp, string pkgName, string member) {
|
||||
exists(NPMPackage pkg |
|
||||
exists(NpmPackage pkg |
|
||||
imp = getAModuleMemberImport(pkg, pkgName, member) and
|
||||
pkgName.regexpMatch("[^./].*")
|
||||
)
|
||||
@@ -212,7 +212,7 @@ private module NpmPackagePortal {
|
||||
|
||||
/** Gets the main module of package `pkgName`. */
|
||||
Module packageMain(string pkgName) {
|
||||
exists(PackageJSON pkg |
|
||||
exists(PackageJson pkg |
|
||||
// don't construct portals for private packages
|
||||
not pkg.isPrivate() and
|
||||
// don't construct portals for vendored-in packages
|
||||
|
||||
@@ -146,7 +146,8 @@ class SourceNode extends DataFlow::Node {
|
||||
* that is, `o.m(...)` or `o[p](...)`.
|
||||
*/
|
||||
DataFlow::CallNode getAChainedMethodCall(string methodName) {
|
||||
result = getAMethodCall*().getAMethodCall(methodName)
|
||||
// the direct call to `getAMethodCall` is needed in case the base is not a `DataFlow::CallNode`.
|
||||
result = [getAMethodCall+().getAMethodCall(methodName), getAMethodCall(methodName)]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,13 +302,13 @@ module SourceNode {
|
||||
*/
|
||||
class DefaultRange extends Range {
|
||||
DefaultRange() {
|
||||
exists(ASTNode astNode | this = DataFlow::valueNode(astNode) |
|
||||
exists(AstNode astNode | this = DataFlow::valueNode(astNode) |
|
||||
astNode instanceof PropAccess or
|
||||
astNode instanceof Function or
|
||||
astNode instanceof ClassDefinition or
|
||||
astNode instanceof ObjectExpr or
|
||||
astNode instanceof ArrayExpr or
|
||||
astNode instanceof JSXNode or
|
||||
astNode instanceof JsxNode or
|
||||
astNode instanceof GlobalVarAccess or
|
||||
astNode instanceof ExternalModuleReference or
|
||||
astNode instanceof RegExpLiteral or
|
||||
@@ -395,7 +396,3 @@ SourceNode moduleVarNode(Module m) { result.(ModuleVarNode).getModule() = m }
|
||||
|
||||
/** Gets the CommonJS/AMD `exports` variable for module `m`. */
|
||||
SourceNode exportsVarNode(Module m) { result.(ExportsVarNode).getModule() = m }
|
||||
|
||||
deprecated class DefaultSourceNode extends SourceNode {
|
||||
DefaultSourceNode() { this instanceof SourceNode::DefaultRange }
|
||||
}
|
||||
|
||||
@@ -62,24 +62,6 @@ module TaintTracking {
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizerEdge` instead.
|
||||
*
|
||||
* Holds if the edge from `source` to `sink` is a taint sanitizer.
|
||||
*/
|
||||
deprecated predicate isSanitizer(DataFlow::Node source, DataFlow::Node sink) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizerEdge` instead.
|
||||
*
|
||||
* 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
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
/** Holds if the edge from `pred` to `succ` is a taint sanitizer. */
|
||||
predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
@@ -447,9 +429,10 @@ module TaintTracking {
|
||||
|
||||
/**
|
||||
* Holds if `pred -> succ` is a taint propagating data flow edge through a string operation.
|
||||
* DEPRECATED: Use `stringConcatenationStep` and `stringManipulationStep` instead.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate stringStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
deprecated predicate stringStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
stringConcatenationStep(pred, succ) or
|
||||
stringManipulationStep(pred, succ)
|
||||
}
|
||||
@@ -551,7 +534,10 @@ module TaintTracking {
|
||||
or
|
||||
// reading from a tainted object yields a tainted result
|
||||
succ.(DataFlow::PropRead).getBase() = pred and
|
||||
not AccessPath::DominatingPaths::hasDominatingWrite(succ) and
|
||||
not (
|
||||
AccessPath::DominatingPaths::hasDominatingWrite(succ) and
|
||||
exists(succ.(DataFlow::PropRead).getPropertyName())
|
||||
) and
|
||||
not isSafeClientSideUrlProperty(succ) and
|
||||
not ClassValidator::isAccessToSanitizedField(succ)
|
||||
or
|
||||
@@ -570,11 +556,10 @@ module TaintTracking {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use the predicate `TaintTracking::persistentStorageStep` instead.
|
||||
*
|
||||
* A taint propagating data flow edge through persistent storage.
|
||||
* Use `TaintTracking::persistentStorageStep` instead of accessing this class.
|
||||
*/
|
||||
deprecated class PersistentStorageTaintStep extends SharedTaintStep {
|
||||
private class PersistentStorageTaintStep extends SharedTaintStep {
|
||||
override predicate persistentStorageStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(PersistentReadAccess read |
|
||||
pred = read.getAWrite().getValue() and
|
||||
@@ -583,8 +568,6 @@ module TaintTracking {
|
||||
}
|
||||
}
|
||||
|
||||
deprecated predicate arrayFunctionTaintStep = ArrayTaintTracking::arrayFunctionTaintStep/3;
|
||||
|
||||
/**
|
||||
* A taint propagating data flow edge for assignments of the form `o[k] = v`, where
|
||||
* one of the following holds:
|
||||
@@ -1175,9 +1158,6 @@ module TaintTracking {
|
||||
polarity = guard.asExpr().(EqualityTest).getPolarity()
|
||||
}
|
||||
|
||||
/** DEPRECATED. This class has been renamed to `MembershipTestSanitizer`. */
|
||||
deprecated class StringInclusionSanitizer = MembershipTestSanitizer;
|
||||
|
||||
/**
|
||||
* A test of form `x.length === "0"`, preventing `x` from being tainted.
|
||||
*/
|
||||
@@ -1200,9 +1180,6 @@ module TaintTracking {
|
||||
override predicate appliesTo(Configuration cfg) { any() }
|
||||
}
|
||||
|
||||
/** DEPRECATED. This class has been renamed to `MembershipTestSanitizer`. */
|
||||
deprecated class InclusionSanitizer = MembershipTestSanitizer;
|
||||
|
||||
/**
|
||||
* A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch.
|
||||
*/
|
||||
@@ -1244,38 +1221,6 @@ module TaintTracking {
|
||||
override predicate appliesTo(Configuration cfg) { any() }
|
||||
}
|
||||
|
||||
/** Gets a variable that is defined exactly once. */
|
||||
private Variable singleDef() { strictcount(result.getADefinition()) = 1 }
|
||||
|
||||
/**
|
||||
* A check of the form `if(x == 'some-constant')`, which sanitizes `x` in its "then" branch.
|
||||
*
|
||||
* DEPRECATED: use `MembershipTestSanitizer` instead.
|
||||
*/
|
||||
deprecated class ConstantComparison extends SanitizerGuardNode, DataFlow::ValueNode {
|
||||
Expr x;
|
||||
override EqualityTest astNode;
|
||||
|
||||
ConstantComparison() {
|
||||
exists(Expr const | astNode.hasOperands(x, const) |
|
||||
// either the other operand is a constant
|
||||
const instanceof ConstantExpr
|
||||
or
|
||||
// or it's an access to a variable that probably acts as a symbolic constant
|
||||
const = singleDef().getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
outcome = astNode.getPolarity() and x = e
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this guard applies to the flow in `cfg`.
|
||||
*/
|
||||
predicate appliesTo(Configuration cfg) { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An equality test on `e.origin` or `e.source` where `e` is a `postMessage` event object,
|
||||
* considered as a sanitizer for `e`.
|
||||
@@ -1301,8 +1246,9 @@ module TaintTracking {
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `pred` to `succ` in one local (intra-procedural) step.
|
||||
* DEPRECATED: Use `TaintTracking::sharedTaintStep` and `DataFlow::Node::getALocalSource()` instead.
|
||||
*/
|
||||
predicate localTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
deprecated predicate localTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
DataFlow::localFlowStep(pred, succ) or
|
||||
sharedTaintStep(pred, succ)
|
||||
}
|
||||
|
||||
@@ -1,425 +0,0 @@
|
||||
/**
|
||||
* DEPRECATED: Use `TypeTracking.qll` instead.
|
||||
*
|
||||
* The following `TrackedNode` usage is usually equivalent to the type tracking usage below.
|
||||
*
|
||||
* ```
|
||||
* class MyTrackedNode extends TrackedNode {
|
||||
* MyTrackedNode() { isInteresting(this) }
|
||||
* }
|
||||
*
|
||||
* DataFlow::Node getMyTrackedNodeLocation(MyTrackedNode n) {
|
||||
* n.flowsTo(result)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ```
|
||||
* DataFlow::SourceNode getMyTrackedNodeLocation(DataFlow::SourceNode start, DataFlow::TypeTracker t) {
|
||||
* t.start() and
|
||||
* isInteresting(result) and
|
||||
* result = start
|
||||
* or
|
||||
* exists (DataFlow::TypeTracker t2 |
|
||||
* result = getMyTrackedNodeLocation(start, t2).track(t2, t)
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* DataFlow::SourceNode getMyTrackedNodeLocation(DataFlow::SourceNode n) {
|
||||
* result = getMyTrackedNodeLocation(n, DataFlow::TypeTracker::end())
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In rare cases, additional tracking is required, for instance when tracking string constants, and the following type tracking formulation is required instead.
|
||||
*
|
||||
* ```
|
||||
* DataFlow::Node getMyTrackedNodeLocation(DataFlow::Node start, DataFlow::TypeTracker t) {
|
||||
* t.start() and
|
||||
* isInteresting(result) and
|
||||
* result = start
|
||||
* or
|
||||
* exists(DataFlow::TypeTracker t2 |
|
||||
* t = t2.smallstep(getMyTrackedNodeLocation(start, t2), result)
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* DataFlow::Node getMyTrackedNodeLocation(DataFlow::Node n) {
|
||||
* result = getMyTrackedNodeLocation(n, DataFlow::TypeTracker::end())
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Provides support for inter-procedural tracking of a customizable
|
||||
* set of data flow nodes.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import internal.FlowSteps as FlowSteps
|
||||
|
||||
/**
|
||||
* A data flow node that should be tracked inter-procedurally.
|
||||
*
|
||||
* To track additional values, extends this class with additional
|
||||
* subclasses.
|
||||
*/
|
||||
abstract deprecated class TrackedNode extends DataFlow::Node {
|
||||
/**
|
||||
* Holds if this node flows into `sink` in zero or more (possibly
|
||||
* inter-procedural) steps.
|
||||
*/
|
||||
predicate flowsTo(DataFlow::Node sink) { NodeTracking::flowsTo(this, sink, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression whose value should be tracked inter-procedurally.
|
||||
*
|
||||
* To track additional expressions, extends this class with additional
|
||||
* subclasses.
|
||||
*/
|
||||
abstract deprecated class TrackedExpr extends Expr {
|
||||
predicate flowsTo(Expr sink) {
|
||||
exists(TrackedExprNode ten | ten.asExpr() = this | ten.flowsTo(DataFlow::valueNode(sink)))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn all `TrackedExpr`s into `TrackedNode`s.
|
||||
*/
|
||||
deprecated private class TrackedExprNode extends TrackedNode {
|
||||
TrackedExprNode() { asExpr() instanceof TrackedExpr }
|
||||
}
|
||||
|
||||
/**
|
||||
* A simplified copy of `Configuration.qll` that implements tracking
|
||||
* of `TrackedNode`s without barriers or additional flow steps.
|
||||
*/
|
||||
private module NodeTracking {
|
||||
private import internal.FlowSteps
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one step from `pred` to `succ`, taking
|
||||
* additional steps into account.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate localFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = succ.getAPredecessor()
|
||||
or
|
||||
DataFlow::SharedFlowStep::step(pred, succ)
|
||||
or
|
||||
localExceptionStep(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a flow step from `pred` to `succ` described by `summary`.
|
||||
*
|
||||
* Summary steps through function calls are not taken into account.
|
||||
*/
|
||||
deprecated private predicate basicFlowStep(
|
||||
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
|
||||
) {
|
||||
isRelevant(pred) and
|
||||
(
|
||||
// Local flow
|
||||
localFlowStep(pred, succ) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
// Flow through properties of objects
|
||||
propertyFlowStep(pred, succ) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
// Flow through global variables
|
||||
globalFlowStep(pred, succ) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
// Flow into function
|
||||
callStep(pred, succ) and
|
||||
summary = PathSummary::call()
|
||||
or
|
||||
// Flow out of function
|
||||
returnStep(pred, succ) and
|
||||
summary = PathSummary::return()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nd` may be reachable from a tracked node.
|
||||
*
|
||||
* No call/return matching is done, so this is a relatively coarse over-approximation.
|
||||
*/
|
||||
deprecated private predicate isRelevant(DataFlow::Node nd) {
|
||||
nd instanceof TrackedNode
|
||||
or
|
||||
exists(DataFlow::Node mid | isRelevant(mid) |
|
||||
basicFlowStep(mid, nd, _)
|
||||
or
|
||||
basicStoreStep(mid, nd, _)
|
||||
or
|
||||
basicLoadStep(mid, nd, _)
|
||||
or
|
||||
exploratoryCallbackStep(mid, nd)
|
||||
or
|
||||
nd = mid.(DataFlow::FunctionNode).getAParameter()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `pred` is an input to `f` which is passed to `succ` at `invk`; that is,
|
||||
* either `pred` is an argument of `f` and `succ` the corresponding parameter, or
|
||||
* `pred` is a variable definition whose value is captured by `f` at `succ`.
|
||||
*/
|
||||
deprecated private predicate callInputStep(
|
||||
Function f, DataFlow::Node invk, DataFlow::Node pred, DataFlow::Node succ
|
||||
) {
|
||||
isRelevant(pred) and
|
||||
(
|
||||
argumentPassing(invk, pred, f, succ)
|
||||
or
|
||||
exists(LocalVariable variable, SsaDefinition def |
|
||||
pred = DataFlow::capturedVariableNode(variable) and
|
||||
calls(invk, f) and
|
||||
captures(f, variable, def) and
|
||||
succ = DataFlow::ssaDefinitionNode(def)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `input`, which is either an argument to `f` at `invk` or a definition
|
||||
* that is captured by `f`, may flow to `nd` (possibly through callees, but not containing
|
||||
* any unmatched calls or returns) along a path summarized by `summary`.
|
||||
*/
|
||||
deprecated private predicate reachableFromInput(
|
||||
Function f, DataFlow::Node invk, DataFlow::Node input, DataFlow::Node nd, PathSummary summary
|
||||
) {
|
||||
callInputStep(f, invk, input, nd) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
|
||||
reachableFromInput(f, invk, input, mid, oldSummary) and
|
||||
flowStep(mid, nd, newSummary) and
|
||||
newSummary.isLevel() and
|
||||
summary = oldSummary.append(newSummary)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nd` may flow into a return statement of `f`
|
||||
* (possibly through callees) along a path summarized by `summary`.
|
||||
*/
|
||||
deprecated private predicate reachesReturn(Function f, DataFlow::Node nd, PathSummary summary) {
|
||||
returnExpr(f, nd, _) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
|
||||
flowStep(nd, mid, oldSummary) and
|
||||
reachesReturn(f, mid, newSummary) and
|
||||
summary = oldSummary.append(newSummary)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a function invoked at `invk` may return an expression into which `input`,
|
||||
* which is either an argument or a definition captured by the function, flows,
|
||||
* possibly through callees.
|
||||
*/
|
||||
deprecated private predicate flowThroughCall(DataFlow::Node input, DataFlow::Node output) {
|
||||
exists(Function f, DataFlow::ValueNode ret |
|
||||
ret.asExpr() = f.getAReturnedExpr() and
|
||||
reachableFromInput(f, output, input, ret, _)
|
||||
)
|
||||
or
|
||||
exists(Function f, DataFlow::Node invk, DataFlow::Node ret |
|
||||
DataFlow::exceptionalFunctionReturnNode(ret, f) and
|
||||
DataFlow::exceptionalInvocationReturnNode(output, invk.asExpr()) and
|
||||
calls(invk, f) and
|
||||
reachableFromInput(f, invk, input, ret, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `pred` may flow into property `prop` of `succ` along a path summarized by `summary`.
|
||||
*/
|
||||
deprecated private predicate storeStep(
|
||||
DataFlow::Node pred, DataFlow::SourceNode succ, string prop, PathSummary summary
|
||||
) {
|
||||
basicStoreStep(pred, succ, prop) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
exists(Function f, DataFlow::Node mid | not f.isAsyncOrGenerator() |
|
||||
// `f` stores its parameter `pred` in property `prop` of a value that flows back to the caller,
|
||||
// and `succ` is an invocation of `f`
|
||||
reachableFromInput(f, succ, pred, mid, summary) and
|
||||
(
|
||||
returnedPropWrite(f, _, prop, mid)
|
||||
or
|
||||
succ instanceof DataFlow::NewNode and
|
||||
receiverPropWrite(f, prop, mid)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if property `prop` of `pred` may flow into `succ` along a path summarized by
|
||||
* `summary`.
|
||||
*/
|
||||
deprecated 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 | not f.isAsyncOrGenerator() |
|
||||
argumentPassing(succ, pred, f, parm) and
|
||||
reachesReturn(f, parm.getAPropertyRead(prop), summary)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `rhs` is the right-hand side of a write to property `prop`, and `nd` is reachable
|
||||
* from the base of that write (possibly through callees) along a path summarized by `summary`.
|
||||
*/
|
||||
deprecated private predicate reachableFromStoreBase(
|
||||
string prop, DataFlow::Node rhs, DataFlow::Node nd, PathSummary summary
|
||||
) {
|
||||
storeStep(rhs, nd, prop, summary)
|
||||
or
|
||||
exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
|
||||
reachableFromStoreBase(prop, rhs, mid, oldSummary) and
|
||||
flowStep(mid, nd, newSummary) and
|
||||
summary = oldSummary.append(newSummary)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the value of `pred` is written to a property of some base object, and that base
|
||||
* object may flow into the base of property read `succ` along a path summarized by `summary`.
|
||||
*
|
||||
* In other words, `pred` may flow to `succ` through a property.
|
||||
*/
|
||||
deprecated private predicate flowThroughProperty(
|
||||
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
|
||||
) {
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` and `cb` are passed as arguments to a function which in turn
|
||||
* invokes `cb`, passing `arg` as its `i`th argument. `arg` flows along a path summarized
|
||||
* by `summary`, while `cb` is only tracked locally.
|
||||
*/
|
||||
deprecated private predicate summarizedHigherOrderCall(
|
||||
DataFlow::Node arg, DataFlow::Node cb, int i, PathSummary summary
|
||||
) {
|
||||
exists(
|
||||
Function f, DataFlow::InvokeNode outer, DataFlow::InvokeNode inner, int j,
|
||||
DataFlow::Node innerArg, DataFlow::SourceNode cbParm, PathSummary oldSummary
|
||||
|
|
||||
reachableFromInput(f, outer, arg, innerArg, oldSummary) and
|
||||
argumentPassing(outer, cb, f, cbParm) and
|
||||
innerArg = inner.getArgument(j)
|
||||
|
|
||||
// direct higher-order call
|
||||
cbParm.flowsTo(inner.getCalleeNode()) and
|
||||
i = j and
|
||||
summary = oldSummary
|
||||
or
|
||||
// indirect higher-order call
|
||||
exists(DataFlow::Node cbArg, PathSummary newSummary |
|
||||
cbParm.flowsTo(cbArg) and
|
||||
summarizedHigherOrderCall(innerArg, cbArg, i, newSummary) and
|
||||
summary = oldSummary.append(PathSummary::call()).append(newSummary)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is passed as the `i`th argument to `callback` through a callback invocation.
|
||||
*
|
||||
* This can be a summarized call, that is, `arg` and `callback` flow into a call,
|
||||
* `f(arg, callback)`, which performs the invocation.
|
||||
*
|
||||
* Alternatively, the callback can flow into a call `f(callback)` which itself provides the `arg`.
|
||||
* That is, `arg` refers to a value defined in `f` or one of its callees.
|
||||
*/
|
||||
deprecated predicate higherOrderCall(
|
||||
DataFlow::Node arg, DataFlow::SourceNode callback, int i, PathSummary summary
|
||||
) {
|
||||
// Summarized call
|
||||
exists(DataFlow::Node cb |
|
||||
summarizedHigherOrderCall(arg, cb, i, summary) and
|
||||
callback.flowsTo(cb)
|
||||
)
|
||||
or
|
||||
// Local invocation of a parameter
|
||||
isRelevant(arg) and
|
||||
exists(DataFlow::InvokeNode invoke |
|
||||
arg = invoke.getArgument(i) and
|
||||
invoke = callback.(DataFlow::ParameterNode).getACall() and
|
||||
summary = PathSummary::call()
|
||||
)
|
||||
or
|
||||
// Forwarding of the callback parameter (but not the argument).
|
||||
// We use a return summary since flow moves back towards the call site.
|
||||
// This ensures that an argument that is only tainted in some contexts cannot flow
|
||||
// out to every callback.
|
||||
exists(DataFlow::Node cbArg, DataFlow::SourceNode innerCb, PathSummary oldSummary |
|
||||
higherOrderCall(arg, innerCb, i, oldSummary) and
|
||||
callStep(cbArg, innerCb) and
|
||||
callback.flowsTo(cbArg) and
|
||||
summary = PathSummary::return().append(oldSummary)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `pred` is passed as an argument to a function `f` which also takes a
|
||||
* callback parameter `cb` and then invokes `cb`, passing `pred` into parameter `succ`
|
||||
* of `cb`. `arg` flows along a path summarized by `summary`, while `cb` is only tracked
|
||||
* locally.
|
||||
*/
|
||||
deprecated private predicate flowIntoHigherOrderCall(
|
||||
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
|
||||
) {
|
||||
exists(DataFlow::FunctionNode cb, int i, PathSummary oldSummary |
|
||||
higherOrderCall(pred, cb, i, oldSummary) and
|
||||
succ = cb.getParameter(i) and
|
||||
summary = oldSummary.append(PathSummary::call())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a flow step from `pred` to `succ` described by `summary`.
|
||||
*/
|
||||
deprecated private predicate flowStep(
|
||||
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
|
||||
) {
|
||||
basicFlowStep(pred, succ, summary)
|
||||
or
|
||||
// Flow through a function that returns a value that depends on one of its arguments
|
||||
// or a captured variable
|
||||
flowThroughCall(pred, succ) and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
// Flow through a property write/read pair
|
||||
flowThroughProperty(pred, succ, summary)
|
||||
or
|
||||
// Flow into higher-order call
|
||||
flowIntoHigherOrderCall(pred, succ, summary)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a path from `source` to `nd` along a path summarized by
|
||||
* `summary`.
|
||||
*/
|
||||
deprecated predicate flowsTo(TrackedNode source, DataFlow::Node nd, PathSummary summary) {
|
||||
source = nd and
|
||||
summary = PathSummary::level()
|
||||
or
|
||||
exists(DataFlow::Node pred, PathSummary oldSummary, PathSummary newSummary |
|
||||
flowsTo(source, pred, oldSummary) and
|
||||
flowStep(pred, nd, newSummary) and
|
||||
summary = oldSummary.append(newSummary)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -129,8 +129,8 @@ private class AnalyzedEnumDeclaration extends DataFlow::AnalyzedValueNode {
|
||||
/**
|
||||
* Flow analysis for JSX elements and fragments.
|
||||
*/
|
||||
private class AnalyzedJSXNode extends DataFlow::AnalyzedValueNode {
|
||||
override JSXNode astNode;
|
||||
private class AnalyzedJsxNode extends DataFlow::AnalyzedValueNode {
|
||||
override JsxNode astNode;
|
||||
|
||||
override AbstractValue getALocalValue() { result = TAbstractOtherObject() }
|
||||
}
|
||||
@@ -138,8 +138,8 @@ private class AnalyzedJSXNode extends DataFlow::AnalyzedValueNode {
|
||||
/**
|
||||
* Flow analysis for qualified JSX names.
|
||||
*/
|
||||
private class AnalyzedJSXQualifiedName extends DataFlow::AnalyzedValueNode {
|
||||
override JSXQualifiedName astNode;
|
||||
private class AnalyzedJsxQualifiedName extends DataFlow::AnalyzedValueNode {
|
||||
override JsxQualifiedName astNode;
|
||||
|
||||
override AbstractValue getALocalValue() { result = TAbstractOtherObject() }
|
||||
}
|
||||
@@ -147,8 +147,8 @@ private class AnalyzedJSXQualifiedName extends DataFlow::AnalyzedValueNode {
|
||||
/**
|
||||
* Flow analysis for empty JSX expressions.
|
||||
*/
|
||||
private class AnalyzedJSXEmptyExpression extends DataFlow::AnalyzedValueNode {
|
||||
override JSXEmptyExpr astNode;
|
||||
private class AnalyzedJsxEmptyExpression extends DataFlow::AnalyzedValueNode {
|
||||
override JsxEmptyExpr astNode;
|
||||
|
||||
override AbstractValue getALocalValue() { result = TAbstractUndefined() }
|
||||
}
|
||||
|
||||
@@ -380,9 +380,10 @@ 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() }
|
||||
AnalyzedClosureExportAssign() {
|
||||
astNode.getLhs() = any(Closure::ClosureModule mod).getExportsVariable().getAReference()
|
||||
}
|
||||
|
||||
override predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source) {
|
||||
baseVal = TAbstractModuleObject(astNode.getTopLevel()) and
|
||||
|
||||
@@ -302,12 +302,11 @@ private class TypeInferredMethodWithAnalyzedReturnFlow extends CallWithNonLocalA
|
||||
* Propagates receivers into locally defined callbacks of partial invocations.
|
||||
*/
|
||||
private class AnalyzedThisInPartialInvokeCallback extends AnalyzedNode, DataFlow::ThisNode {
|
||||
DataFlow::PartialInvokeNode call;
|
||||
DataFlow::Node receiver;
|
||||
|
||||
AnalyzedThisInPartialInvokeCallback() {
|
||||
exists(DataFlow::Node callbackArg |
|
||||
receiver = call.getBoundReceiver(callbackArg) and
|
||||
receiver = any(DataFlow::PartialInvokeNode call).getBoundReceiver(callbackArg) and
|
||||
getBinder().flowsTo(callbackArg)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ class AnalyzedVarDef extends VarDef {
|
||||
/**
|
||||
* Gets the toplevel syntactic unit to which this definition belongs.
|
||||
*/
|
||||
TopLevel getTopLevel() { result = this.(ASTNode).getTopLevel() }
|
||||
TopLevel getTopLevel() { result = this.(AstNode).getTopLevel() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,9 +35,12 @@ abstract class Dependency extends Locatable {
|
||||
* the source tree, or a package that is referenced as a dependency
|
||||
* in a `package.json` file.
|
||||
*/
|
||||
abstract class NPMDependency extends Dependency {
|
||||
abstract class NpmDependency extends Dependency {
|
||||
/** Gets the name of the NPM package this module belongs to. */
|
||||
abstract string getNPMPackageName();
|
||||
abstract string getNpmPackageName();
|
||||
|
||||
/** DEPRECATED: Alias for getNpmPackageName */
|
||||
deprecated string getNPMPackageName() { result = this.getNpmPackageName() }
|
||||
|
||||
/** Gets the version of the NPM package this module belongs to. */
|
||||
abstract string getVersion();
|
||||
@@ -46,7 +49,7 @@ abstract class NPMDependency extends Dependency {
|
||||
abstract Import getAnImport();
|
||||
|
||||
override predicate info(string id, string v) {
|
||||
id = this.getNPMPackageName() and
|
||||
id = this.getNpmPackageName() and
|
||||
v = this.getVersion()
|
||||
}
|
||||
|
||||
@@ -59,6 +62,9 @@ abstract class NPMDependency extends Dependency {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for NpmDependency */
|
||||
deprecated class NPMDependency = NpmDependency;
|
||||
|
||||
/**
|
||||
* Gets a variable into which something is imported by `i`.
|
||||
*/
|
||||
@@ -83,23 +89,26 @@ private Expr propAccessOn(Expr e) { result.(PropAccess).getBase() = e }
|
||||
* included in the database (as opposed to an `ExternalNPMDependency`
|
||||
* which is only referenced in a `package.json` file).
|
||||
*/
|
||||
class BundledNPMDependency extends NPMDependency {
|
||||
BundledNPMDependency() {
|
||||
exists(NPMPackage pkg | this = pkg.getAModule() |
|
||||
class BundledNpmDependency extends NpmDependency {
|
||||
BundledNpmDependency() {
|
||||
exists(NpmPackage pkg | this = pkg.getAModule() |
|
||||
// exclude packages marked "private": they have no globally unique ID
|
||||
not pkg.getPackageJSON().isPrivate()
|
||||
not pkg.getPackageJson().isPrivate()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the package to which this module belongs. */
|
||||
private NPMPackage getPackage() { this = result.getAModule() }
|
||||
private NpmPackage getPackage() { this = result.getAModule() }
|
||||
|
||||
/** Gets the `package.json` of the package to which this module belongs. */
|
||||
private PackageJSON getPackageJSON() { result = this.getPackage().getPackageJSON() }
|
||||
private PackageJson getPackageJson() { result = this.getPackage().getPackageJson() }
|
||||
|
||||
override string getNPMPackageName() { result = this.getPackageJSON().getPackageName() }
|
||||
override string getNpmPackageName() { result = this.getPackageJson().getPackageName() }
|
||||
|
||||
override string getVersion() { result = this.getPackageJSON().getVersion() }
|
||||
/** DEPRECATED: Alias for getNpmPackageName */
|
||||
deprecated override string getNPMPackageName() { result = this.getNpmPackageName() }
|
||||
|
||||
override string getVersion() { result = this.getPackageJson().getVersion() }
|
||||
|
||||
override Import getAnImport() {
|
||||
this = result.getImportedModule() and
|
||||
@@ -108,27 +117,33 @@ class BundledNPMDependency extends NPMDependency {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for BundledNpmDependency */
|
||||
deprecated class BundledNPMDependency = BundledNpmDependency;
|
||||
|
||||
/**
|
||||
* An NPM package referenced in a `package.json` file.
|
||||
*/
|
||||
class ExternalNPMDependency extends NPMDependency {
|
||||
ExternalNPMDependency() {
|
||||
exists(PackageJSON pkgjson |
|
||||
this.(JSONString) = pkgjson.getADependenciesObject(_).getPropValue(_)
|
||||
class ExternalNpmDependency extends NpmDependency {
|
||||
ExternalNpmDependency() {
|
||||
exists(PackageJson pkgjson |
|
||||
this.(JsonString) = pkgjson.getADependenciesObject(_).getPropValue(_)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the NPM package declaring this dependency. */
|
||||
private NPMPackage getDeclaringPackage() {
|
||||
this = result.getPackageJSON().getADependenciesObject(_).getPropValue(_)
|
||||
private NpmPackage getDeclaringPackage() {
|
||||
this = result.getPackageJson().getADependenciesObject(_).getPropValue(_)
|
||||
}
|
||||
|
||||
override string getNPMPackageName() {
|
||||
override string getNpmPackageName() {
|
||||
exists(PackageDependencies pkgdeps | this = pkgdeps.getPropValue(result))
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getNpmPackageName */
|
||||
deprecated override string getNPMPackageName() { result = this.getNpmPackageName() }
|
||||
|
||||
private string getVersionNumber() {
|
||||
exists(string versionRange | versionRange = this.(JSONString).getValue() |
|
||||
exists(string versionRange | versionRange = this.(JsonString).getValue() |
|
||||
// extract a concrete version from the version range; currently,
|
||||
// we handle exact versions as well as `<=`, `>=`, `~` and `^` ranges
|
||||
result = versionRange.regexpCapture("(?:[><]=|[=~^])?v?(\\d+(\\.\\d+){1,2})", 1)
|
||||
@@ -151,13 +166,16 @@ class ExternalNPMDependency extends NPMDependency {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for ExternalNpmDependency */
|
||||
deprecated class ExternalNPMDependency = ExternalNpmDependency;
|
||||
|
||||
/**
|
||||
* Holds if import `i` may refer to the declared dependency `dep` of package `pkg`,
|
||||
* where the result value is the nesting depth of the file containing `i` within `pkg`.
|
||||
*/
|
||||
private int importsDependency(Import i, NPMPackage pkg, NPMDependency dep) {
|
||||
private int importsDependency(Import i, NpmPackage pkg, NpmDependency dep) {
|
||||
exists(string name |
|
||||
dep = pkg.getPackageJSON().getADependenciesObject(_).getPropValue(name) and
|
||||
dep = pkg.getPackageJson().getADependenciesObject(_).getPropValue(name) and
|
||||
not exists(i.getImportedModule()) and
|
||||
i.getImportedPath().getComponent(0) = name and
|
||||
i.getEnclosingModule() = pkg.getAModule() and
|
||||
|
||||
@@ -125,9 +125,9 @@ abstract class FrameworkLibraryWithMarkerComment extends FrameworkLibrary {
|
||||
* A framework library that is referenced by URLs that have a certain
|
||||
* pattern.
|
||||
*/
|
||||
abstract class FrameworkLibraryWithURLRegex extends FrameworkLibrary {
|
||||
abstract class FrameworkLibraryWithUrlRegex extends FrameworkLibrary {
|
||||
bindingset[this]
|
||||
FrameworkLibraryWithURLRegex() { this = this }
|
||||
FrameworkLibraryWithUrlRegex() { this = this }
|
||||
|
||||
/**
|
||||
* Gets a regular expression that can be used to identify a URL referring
|
||||
@@ -136,9 +136,15 @@ abstract class FrameworkLibraryWithURLRegex extends FrameworkLibrary {
|
||||
* The first capture group of this regular expression should match
|
||||
* the version number.
|
||||
*/
|
||||
abstract string getAURLRegex();
|
||||
abstract string getAUrlRegex();
|
||||
|
||||
/** DEPRECATED: Alias for getAUrlRegex */
|
||||
deprecated string getAURLRegex() { result = this.getAUrlRegex() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for FrameworkLibraryWithUrlRegex */
|
||||
deprecated class FrameworkLibraryWithURLRegex = FrameworkLibraryWithUrlRegex;
|
||||
|
||||
/**
|
||||
* A framework library that is referenced by URLs containing the name
|
||||
* of the framework (or an alias) and a version string.
|
||||
@@ -154,14 +160,14 @@ abstract class FrameworkLibraryWithURLRegex extends FrameworkLibrary {
|
||||
*
|
||||
* See `variantRegex()` below for a discussion of variant suffixes.
|
||||
*/
|
||||
abstract class FrameworkLibraryWithGenericURL extends FrameworkLibraryWithURLRegex {
|
||||
abstract class FrameworkLibraryWithGenericUrl extends FrameworkLibraryWithUrlRegex {
|
||||
bindingset[this]
|
||||
FrameworkLibraryWithGenericURL() { this = this }
|
||||
FrameworkLibraryWithGenericUrl() { this = this }
|
||||
|
||||
/** Gets an alternative name of this library. */
|
||||
string getAnAlias() { none() }
|
||||
|
||||
override string getAURLRegex() {
|
||||
override string getAUrlRegex() {
|
||||
exists(string id | id = this.getId() or id = this.getAnAlias() |
|
||||
result = ".*(?:^|/)" + id + "-(" + semverRegex() + ")" + variantRegex() + "\\.js" or
|
||||
result =
|
||||
@@ -169,8 +175,14 @@ abstract class FrameworkLibraryWithGenericURL extends FrameworkLibraryWithURLReg
|
||||
"\\.js"
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getAUrlRegex */
|
||||
deprecated override string getAURLRegex() { result = this.getAUrlRegex() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for FrameworkLibraryWithGenericUrl */
|
||||
deprecated class FrameworkLibraryWithGenericURL = FrameworkLibraryWithGenericUrl;
|
||||
|
||||
/**
|
||||
* Gets a regular expression identifying suffixes that are commonly appended
|
||||
* to the name of a library to distinguish minor variants.
|
||||
@@ -264,20 +276,23 @@ private predicate matchMarkerComment(
|
||||
/**
|
||||
* A reference to a `FrameworkLibraryWithURL`.
|
||||
*/
|
||||
class FrameworkLibraryReferenceWithURL extends FrameworkLibraryReference {
|
||||
FrameworkLibraryReferenceWithURL() { matchURL(this, _, _) }
|
||||
class FrameworkLibraryReferenceWithUrl extends FrameworkLibraryReference {
|
||||
FrameworkLibraryReferenceWithUrl() { matchUrl(this, _, _) }
|
||||
|
||||
override predicate info(FrameworkLibrary fl, string v) { matchURL(this, fl, v) }
|
||||
override predicate info(FrameworkLibrary fl, string v) { matchUrl(this, fl, v) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for FrameworkLibraryReferenceWithUrl */
|
||||
deprecated class FrameworkLibraryReferenceWithURL = FrameworkLibraryReferenceWithUrl;
|
||||
|
||||
/**
|
||||
* Holds if the value of `src` attribute `attr` matches the URL pattern of library
|
||||
* `fl` at `version`.
|
||||
*/
|
||||
private predicate matchURL(HTML::Attribute attr, FrameworkLibraryWithURLRegex fl, string version) {
|
||||
private predicate matchUrl(HTML::Attribute attr, FrameworkLibraryWithUrlRegex fl, string version) {
|
||||
attr.getName() = "src" and
|
||||
attr.getElement() instanceof HTML::ScriptElement and
|
||||
version = attr.getValue().regexpCapture(fl.getAURLRegex(), 1)
|
||||
version = attr.getValue().regexpCapture(fl.getAUrlRegex(), 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,7 +303,7 @@ private string versionRegex() { result = "\\d+\\.\\d+[A-Za-z0-9.+_-]*" }
|
||||
/**
|
||||
* The jQuery framework.
|
||||
*/
|
||||
private class JQuery extends FrameworkLibraryWithGenericURL {
|
||||
private class JQuery extends FrameworkLibraryWithGenericUrl {
|
||||
JQuery() { this = "jquery" }
|
||||
|
||||
override string getAnEntryPoint() { result = "$" or result = "jQuery" }
|
||||
@@ -331,7 +346,7 @@ private class JQueryInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The jQuery Mobile framework.
|
||||
*/
|
||||
private class JQueryMobile extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class JQueryMobile extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
JQueryMobile() { this = "jquery-mobile" }
|
||||
|
||||
override string getAnAlias() { result = "jquery.mobile" }
|
||||
@@ -344,7 +359,7 @@ private class JQueryMobile extends FrameworkLibraryWithGenericURL, FrameworkLibr
|
||||
/**
|
||||
* The jQuery UI framework.
|
||||
*/
|
||||
private class JQueryUI extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class JQueryUI extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
JQueryUI() { this = "jquery-ui" }
|
||||
|
||||
override string getAMarkerCommentRegex() { result = "(?s).*jQuery UI - v?(<VERSION>).*" }
|
||||
@@ -355,7 +370,7 @@ private class JQueryUI extends FrameworkLibraryWithGenericURL, FrameworkLibraryW
|
||||
/**
|
||||
* The jQuery TextExt framework.
|
||||
*/
|
||||
private class JQueryTextExt extends FrameworkLibraryWithGenericURL,
|
||||
private class JQueryTextExt extends FrameworkLibraryWithGenericUrl,
|
||||
FrameworkLibraryWithMarkerComment {
|
||||
JQueryTextExt() { this = "jquery-textext" }
|
||||
|
||||
@@ -371,7 +386,7 @@ private class JQueryTextExt extends FrameworkLibraryWithGenericURL,
|
||||
/**
|
||||
* The jQuery DataTables framework.
|
||||
*/
|
||||
private class JQueryDataTables extends FrameworkLibraryWithGenericURL,
|
||||
private class JQueryDataTables extends FrameworkLibraryWithGenericUrl,
|
||||
FrameworkLibraryWithMarkerComment {
|
||||
JQueryDataTables() { this = "jquery-dataTables" }
|
||||
|
||||
@@ -385,7 +400,7 @@ private class JQueryDataTables extends FrameworkLibraryWithGenericURL,
|
||||
/**
|
||||
* The jQuery jsTree framework.
|
||||
*/
|
||||
private class JQueryJsTree extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class JQueryJsTree extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
JQueryJsTree() { this = "jquery-jstree" }
|
||||
|
||||
override string getAnAlias() { result = "jquery.jstree" }
|
||||
@@ -396,7 +411,7 @@ private class JQueryJsTree extends FrameworkLibraryWithGenericURL, FrameworkLibr
|
||||
/**
|
||||
* The jQuery Snippet framework.
|
||||
*/
|
||||
private class JQuerySnippet extends FrameworkLibraryWithGenericURL,
|
||||
private class JQuerySnippet extends FrameworkLibraryWithGenericUrl,
|
||||
FrameworkLibraryWithMarkerComment {
|
||||
JQuerySnippet() { this = "jquery-snippet" }
|
||||
|
||||
@@ -410,7 +425,7 @@ private class JQuerySnippet extends FrameworkLibraryWithGenericURL,
|
||||
/**
|
||||
* The Bootstrap framework.
|
||||
*/
|
||||
private class Bootstrap extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class Bootstrap extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
Bootstrap() { this = "bootstrap" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -423,7 +438,7 @@ private class Bootstrap extends FrameworkLibraryWithGenericURL, FrameworkLibrary
|
||||
/**
|
||||
* The Modernizr framework.
|
||||
*/
|
||||
private class Modernizr extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class Modernizr extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
Modernizr() { this = "modernizr" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -436,7 +451,7 @@ private class Modernizr extends FrameworkLibraryWithGenericURL, FrameworkLibrary
|
||||
/**
|
||||
* The MooTools framework.
|
||||
*/
|
||||
private class MooTools extends FrameworkLibraryWithGenericURL {
|
||||
private class MooTools extends FrameworkLibraryWithGenericUrl {
|
||||
MooTools() { this = "mootools" }
|
||||
|
||||
override string getAnEntryPoint() { /* not easily detectable */ none() }
|
||||
@@ -479,7 +494,7 @@ private class MooToolsInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The Prototype framework.
|
||||
*/
|
||||
private class Prototype extends FrameworkLibraryWithGenericURL {
|
||||
private class Prototype extends FrameworkLibraryWithGenericUrl {
|
||||
Prototype() { this = "prototype" }
|
||||
|
||||
override string getAnEntryPoint() { /* not easily detectable */ none() }
|
||||
@@ -518,7 +533,7 @@ private class PrototypeInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The Scriptaculous framework.
|
||||
*/
|
||||
private class Scriptaculous extends FrameworkLibraryWithGenericURL {
|
||||
private class Scriptaculous extends FrameworkLibraryWithGenericUrl {
|
||||
Scriptaculous() { this = "scriptaculous" }
|
||||
|
||||
override string getAnEntryPoint() { /* not easily detectable */ none() }
|
||||
@@ -557,7 +572,7 @@ private class ScriptaculousInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The Underscore framework.
|
||||
*/
|
||||
private class Underscore extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class Underscore extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
Underscore() { this = "underscore" }
|
||||
|
||||
override string getAMarkerCommentRegex() { result = "^\\s*Underscore.js (<VERSION>).*" }
|
||||
@@ -568,7 +583,7 @@ private class Underscore extends FrameworkLibraryWithGenericURL, FrameworkLibrar
|
||||
/**
|
||||
* The Lodash framework.
|
||||
*/
|
||||
private class Lodash extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class Lodash extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
Lodash() { this = "lodash" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -581,7 +596,7 @@ private class Lodash extends FrameworkLibraryWithGenericURL, FrameworkLibraryWit
|
||||
}
|
||||
|
||||
/** The Dojo framework. */
|
||||
private class Dojo extends FrameworkLibraryWithGenericURL {
|
||||
private class Dojo extends FrameworkLibraryWithGenericUrl {
|
||||
Dojo() { this = "dojo" }
|
||||
|
||||
override string getAnEntryPoint() { result = "dojo" }
|
||||
@@ -613,7 +628,7 @@ private class DojoInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The ExtJS framework.
|
||||
*/
|
||||
private class ExtJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class ExtJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
ExtJS() { this = "extjs" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -629,7 +644,7 @@ private class ExtJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWith
|
||||
/**
|
||||
* The YUI framework.
|
||||
*/
|
||||
private class YUI extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class YUI extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
YUI() { this = "yui" }
|
||||
|
||||
override string getAMarkerCommentRegex() { result = "(?s).*YUI (<VERSION>) \\(build \\d+\\).*" }
|
||||
@@ -640,7 +655,7 @@ private class YUI extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMa
|
||||
/**
|
||||
* The Knockout framework.
|
||||
*/
|
||||
private class Knockout extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class Knockout extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
Knockout() { this = "knockout" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -653,7 +668,7 @@ private class Knockout extends FrameworkLibraryWithGenericURL, FrameworkLibraryW
|
||||
/**
|
||||
* The AngularJS framework.
|
||||
*/
|
||||
private class AngularJS extends FrameworkLibraryWithGenericURL {
|
||||
private class AngularJS extends FrameworkLibraryWithGenericUrl {
|
||||
AngularJS() { this = "angularjs" }
|
||||
|
||||
override string getAnAlias() { result = "angular" or result = "angular2" }
|
||||
@@ -691,7 +706,7 @@ private class AngularJSInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The Angular UI bootstrap framework.
|
||||
*/
|
||||
private class AngularUIBootstrap extends FrameworkLibraryWithGenericURL {
|
||||
private class AngularUIBootstrap extends FrameworkLibraryWithGenericUrl {
|
||||
AngularUIBootstrap() { this = "angular-ui-bootstrap" }
|
||||
|
||||
override string getAnAlias() { result = "ui-bootstrap" }
|
||||
@@ -722,7 +737,7 @@ private class AngularUIBootstrapInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The React framework.
|
||||
*/
|
||||
private class React extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class React extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
React() { this = "react" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -733,15 +748,15 @@ private class React extends FrameworkLibraryWithGenericURL, FrameworkLibraryWith
|
||||
/**
|
||||
* The Microsoft AJAX Framework.
|
||||
*/
|
||||
private class MicrosoftAJAXFramework extends FrameworkLibrary {
|
||||
MicrosoftAJAXFramework() { this = "microsoft-ajax-framework" }
|
||||
private class MicrosoftAjaxFramework extends FrameworkLibrary {
|
||||
MicrosoftAjaxFramework() { this = "microsoft-ajax-framework" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if comments `c1` and `c2` in toplevel `tl` are marker comments for the given
|
||||
* `version` of the Microsoft AJAX Framework.
|
||||
*/
|
||||
private predicate microsoftAJAXFrameworkMarkerComments(
|
||||
private predicate microsoftAjaxFrameworkMarkerComments(
|
||||
Comment c1, Comment c2, TopLevel tl, string version
|
||||
) {
|
||||
tl = c1.getTopLevel() and
|
||||
@@ -753,19 +768,19 @@ private predicate microsoftAJAXFrameworkMarkerComments(
|
||||
/**
|
||||
* A copy of the Microsoft AJAX Framework.
|
||||
*/
|
||||
private class MicrosoftAJAXFrameworkInstance extends FrameworkLibraryInstance {
|
||||
MicrosoftAJAXFrameworkInstance() { microsoftAJAXFrameworkMarkerComments(_, _, this, _) }
|
||||
private class MicrosoftAjaxFrameworkInstance extends FrameworkLibraryInstance {
|
||||
MicrosoftAjaxFrameworkInstance() { microsoftAjaxFrameworkMarkerComments(_, _, this, _) }
|
||||
|
||||
override predicate info(FrameworkLibrary fl, string v) {
|
||||
fl instanceof MicrosoftAJAXFramework and
|
||||
microsoftAJAXFrameworkMarkerComments(_, _, this, v)
|
||||
fl instanceof MicrosoftAjaxFramework and
|
||||
microsoftAjaxFrameworkMarkerComments(_, _, this, v)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Polymer framework.
|
||||
*/
|
||||
private class Polymer extends FrameworkLibraryWithGenericURL {
|
||||
private class Polymer extends FrameworkLibraryWithGenericUrl {
|
||||
Polymer() { this = "polymer" }
|
||||
|
||||
override string getAnEntryPoint() { result = "Polymer" }
|
||||
@@ -800,7 +815,7 @@ private class PolymerInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The Vue.js framework.
|
||||
*/
|
||||
private class VueJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class VueJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
VueJS() { this = "vue" }
|
||||
|
||||
override string getAMarkerCommentRegex() { result = "(?s).*Vue\\.js v(<VERSION>).*" }
|
||||
@@ -811,7 +826,7 @@ private class VueJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWith
|
||||
/**
|
||||
* The Swagger UI framework.
|
||||
*/
|
||||
private class SwaggerUI extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class SwaggerUI extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
SwaggerUI() { this = "swagger-ui" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -822,7 +837,7 @@ private class SwaggerUI extends FrameworkLibraryWithGenericURL, FrameworkLibrary
|
||||
/**
|
||||
* The Backbone.js framework.
|
||||
*/
|
||||
private class BackboneJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class BackboneJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
BackboneJS() { this = "backbone" }
|
||||
|
||||
override string getAMarkerCommentRegex() { result = "(?s).*Backbone\\.js (<VERSION>).*" }
|
||||
@@ -833,7 +848,7 @@ private class BackboneJS extends FrameworkLibraryWithGenericURL, FrameworkLibrar
|
||||
/**
|
||||
* The Ember.js framework.
|
||||
*/
|
||||
private class EmberJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class EmberJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
EmberJS() { this = "ember" }
|
||||
|
||||
override string getAMarkerCommentRegex() {
|
||||
@@ -846,7 +861,7 @@ private class EmberJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWi
|
||||
/**
|
||||
* The QUnit.js framework.
|
||||
*/
|
||||
private class QUnitJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class QUnitJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
QUnitJS() { this = "qunit" }
|
||||
|
||||
override string getAMarkerCommentRegex() { result = "(?s).*QUnit\\s*(<VERSION>).*" }
|
||||
@@ -857,28 +872,28 @@ private class QUnitJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWi
|
||||
/**
|
||||
* The Mocha framework.
|
||||
*/
|
||||
private class Mocha extends FrameworkLibraryWithGenericURL {
|
||||
private class Mocha extends FrameworkLibraryWithGenericUrl {
|
||||
Mocha() { this = "mocha" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The Jasmine framework.
|
||||
*/
|
||||
private class Jasmine extends FrameworkLibraryWithGenericURL {
|
||||
private class Jasmine extends FrameworkLibraryWithGenericUrl {
|
||||
Jasmine() { this = "jasmine" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The Chai framework.
|
||||
*/
|
||||
private class Chai extends FrameworkLibraryWithGenericURL {
|
||||
private class Chai extends FrameworkLibraryWithGenericUrl {
|
||||
Chai() { this = "chai" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The Sinon.JS framework.
|
||||
*/
|
||||
private class SinonJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class SinonJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
SinonJS() { this = "sinon" }
|
||||
|
||||
override string getAnAlias() { result = "sinon-ie" or result = "sinon-timers" }
|
||||
@@ -889,7 +904,7 @@ private class SinonJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWi
|
||||
/**
|
||||
* The TinyMCE framework.
|
||||
*/
|
||||
private class TinyMCE extends FrameworkLibraryWithGenericURL {
|
||||
private class TinyMCE extends FrameworkLibraryWithGenericUrl {
|
||||
TinyMCE() { this = "tinymce" }
|
||||
|
||||
override string getAnAlias() { result = "jquery.tinymce" or result = "tinymce.jquery" }
|
||||
@@ -898,7 +913,7 @@ private class TinyMCE extends FrameworkLibraryWithGenericURL {
|
||||
/**
|
||||
* The Require.js framework.
|
||||
*/
|
||||
private class RequireJS extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class RequireJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
RequireJS() { this = "requirejs" }
|
||||
|
||||
override string getAnAlias() { result = "require.js" }
|
||||
@@ -917,7 +932,7 @@ private class ApplicationInsightsInstance extends FrameworkLibraryInstance {
|
||||
this.(TopLevel)
|
||||
.getFile()
|
||||
.getAbsolutePath()
|
||||
.regexpCapture(any(ApplicationInsights t).getAURLRegex(), 1)
|
||||
.regexpCapture(any(ApplicationInsights t).getAUrlRegex(), 1)
|
||||
}
|
||||
|
||||
override predicate info(FrameworkLibrary fl, string v) {
|
||||
@@ -929,16 +944,19 @@ private class ApplicationInsightsInstance extends FrameworkLibraryInstance {
|
||||
/**
|
||||
* The Microsoft ApplicationInsights framework.
|
||||
*/
|
||||
private class ApplicationInsights extends FrameworkLibraryWithURLRegex {
|
||||
private class ApplicationInsights extends FrameworkLibraryWithUrlRegex {
|
||||
ApplicationInsights() { this = "ApplicationInsights" }
|
||||
|
||||
override string getAURLRegex() { result = ".*(?:^|/)ai\\.(" + semverRegex() + ")-build\\d+\\.js" }
|
||||
override string getAUrlRegex() { result = ".*(?:^|/)ai\\.(" + semverRegex() + ")-build\\d+\\.js" }
|
||||
|
||||
/** DEPRECATED: Alias for getAUrlRegex */
|
||||
deprecated override string getAURLRegex() { result = this.getAUrlRegex() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The twitter-text framework.
|
||||
*/
|
||||
private class TwitterText extends FrameworkLibraryWithGenericURL, FrameworkLibraryWithMarkerComment {
|
||||
private class TwitterText extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWithMarkerComment {
|
||||
TwitterText() { this = "twitter-text" }
|
||||
|
||||
override string getAMarkerCommentRegex() { result = "(?s).*twitter-text\\s*(<VERSION>).*" }
|
||||
@@ -947,10 +965,13 @@ private class TwitterText extends FrameworkLibraryWithGenericURL, FrameworkLibra
|
||||
/**
|
||||
* The classic version of twitter-text, as seen in the wild.
|
||||
*/
|
||||
private class TwitterTextClassic extends FrameworkLibraryWithURLRegex {
|
||||
private class TwitterTextClassic extends FrameworkLibraryWithUrlRegex {
|
||||
TwitterTextClassic() { this = "twitter-text" }
|
||||
|
||||
override string getAURLRegex() { result = ".*(?:^|/)twitter_text" + variantRegex() + "\\.js" }
|
||||
override string getAUrlRegex() { result = ".*(?:^|/)twitter_text" + variantRegex() + "\\.js" }
|
||||
|
||||
/** DEPRECATED: Alias for getAUrlRegex */
|
||||
deprecated override string getAURLRegex() { result = this.getAUrlRegex() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -961,7 +982,7 @@ private class TwitterTextClassicInstance extends FrameworkLibraryInstance {
|
||||
this.(TopLevel)
|
||||
.getFile()
|
||||
.getAbsolutePath()
|
||||
.regexpMatch(any(TwitterTextClassic t).getAURLRegex())
|
||||
.regexpMatch(any(TwitterTextClassic t).getAUrlRegex())
|
||||
}
|
||||
|
||||
override predicate info(FrameworkLibrary fl, string v) {
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
import javascript
|
||||
|
||||
private class BackwardExploringConfiguration extends DataFlow::Configuration {
|
||||
DataFlow::Configuration cfg;
|
||||
|
||||
BackwardExploringConfiguration() { this = cfg }
|
||||
BackwardExploringConfiguration() { this = any(DataFlow::Configuration cfg) }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) { any() }
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
import javascript
|
||||
|
||||
private class ForwardExploringConfiguration extends DataFlow::Configuration {
|
||||
DataFlow::Configuration cfg;
|
||||
|
||||
ForwardExploringConfiguration() { this = cfg }
|
||||
ForwardExploringConfiguration() { this = any(DataFlow::Configuration cfg) }
|
||||
|
||||
override predicate isSink(DataFlow::Node node) { any() }
|
||||
|
||||
|
||||
@@ -149,12 +149,10 @@ DataFlow::CallNode moduleRef(AngularModule m) {
|
||||
* A call to a method from the `angular.Module` API.
|
||||
*/
|
||||
class ModuleApiCall extends DataFlow::CallNode {
|
||||
/** The module on which the method is called. */
|
||||
AngularModule mod;
|
||||
/** The name of the called method. */
|
||||
string methodName;
|
||||
|
||||
ModuleApiCall() { this = moduleRef(mod).getAMethodCall(methodName) }
|
||||
ModuleApiCall() { this = moduleRef(_).getAMethodCall(methodName) }
|
||||
|
||||
/**
|
||||
* Gets the name of the invoked method.
|
||||
|
||||
@@ -65,10 +65,9 @@ private string getInterpolatedExpressionPattern() { result = "(?<=\\{\\{).*?(?=\
|
||||
*/
|
||||
private class HtmlTextNodeAsNgSourceProvider extends NgSourceProvider, HTML::TextNode {
|
||||
string source;
|
||||
int offset;
|
||||
|
||||
HtmlTextNodeAsNgSourceProvider() {
|
||||
source = this.getText().regexpFind(getInterpolatedExpressionPattern(), _, offset)
|
||||
source = this.getText().regexpFind(getInterpolatedExpressionPattern(), _, _)
|
||||
}
|
||||
|
||||
override predicate providesSourceAt(
|
||||
|
||||
@@ -46,23 +46,23 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
||||
/**
|
||||
* Gets the `i`th dependency declaration, which is also named `name`.
|
||||
*/
|
||||
abstract ASTNode getDependencyDeclaration(int i, string name);
|
||||
abstract AstNode getDependencyDeclaration(int i, string name);
|
||||
|
||||
/**
|
||||
* Gets an ASTNode for the `name` dependency declaration.
|
||||
*/
|
||||
ASTNode getADependencyDeclaration(string name) { result = getDependencyDeclaration(_, name) }
|
||||
AstNode getADependencyDeclaration(string name) { result = getDependencyDeclaration(_, name) }
|
||||
|
||||
/**
|
||||
* Gets the ASTNode for the `i`th dependency declaration.
|
||||
*/
|
||||
ASTNode getDependencyDeclaration(int i) { result = getDependencyDeclaration(i, _) }
|
||||
AstNode getDependencyDeclaration(int i) { result = getDependencyDeclaration(i, _) }
|
||||
|
||||
/** Gets the function underlying this injectable function. */
|
||||
abstract Function asFunction();
|
||||
|
||||
/** Gets a location where this function is explicitly dependency injected. */
|
||||
abstract ASTNode getAnExplicitDependencyInjection();
|
||||
abstract AstNode getAnExplicitDependencyInjection();
|
||||
|
||||
/**
|
||||
* Gets a service corresponding to the dependency-injected `parameter`.
|
||||
@@ -110,7 +110,7 @@ private class FunctionWithImplicitDependencyAnnotation extends InjectableFunctio
|
||||
|
||||
override Function asFunction() { result = astNode }
|
||||
|
||||
override ASTNode getAnExplicitDependencyInjection() { none() }
|
||||
override AstNode getAnExplicitDependencyInjection() { none() }
|
||||
}
|
||||
|
||||
private DataFlow::PropWrite getAPropertyDependencyInjection(Function function) {
|
||||
@@ -143,7 +143,7 @@ private class FunctionWithInjectProperty extends InjectableFunction {
|
||||
exists(int i | exists(getDependencyDeclaration(i, name)) | result = astNode.getParameter(i))
|
||||
}
|
||||
|
||||
override ASTNode getDependencyDeclaration(int i, string name) {
|
||||
override AstNode getDependencyDeclaration(int i, string name) {
|
||||
exists(DataFlow::ValueNode decl |
|
||||
decl = dependencies.getElement(i) and
|
||||
decl.mayHaveStringValue(name) and
|
||||
@@ -153,7 +153,7 @@ private class FunctionWithInjectProperty extends InjectableFunction {
|
||||
|
||||
override Function asFunction() { result = astNode }
|
||||
|
||||
override ASTNode getAnExplicitDependencyInjection() {
|
||||
override AstNode getAnExplicitDependencyInjection() {
|
||||
result = getAPropertyDependencyInjection(astNode).getAstNode()
|
||||
}
|
||||
}
|
||||
@@ -176,14 +176,14 @@ private class FunctionWithExplicitDependencyAnnotation extends InjectableFunctio
|
||||
)
|
||||
}
|
||||
|
||||
override ASTNode getDependencyDeclaration(int i, string name) {
|
||||
override AstNode getDependencyDeclaration(int i, string name) {
|
||||
result = astNode.getElement(i) and
|
||||
result.(Expr).mayHaveStringValue(name)
|
||||
}
|
||||
|
||||
override Function asFunction() { result = function.getAstNode() }
|
||||
|
||||
override ASTNode getAnExplicitDependencyInjection() {
|
||||
override AstNode getAnExplicitDependencyInjection() {
|
||||
result = astNode or
|
||||
result = function.(InjectableFunction).getAnExplicitDependencyInjection()
|
||||
}
|
||||
|
||||
@@ -9,18 +9,18 @@ module Babel {
|
||||
* A Babel configuration object, either from `package.json` or from a
|
||||
* `.babelrc` file.
|
||||
*/
|
||||
class Config extends JSONObject {
|
||||
class Config extends JsonObject {
|
||||
Config() {
|
||||
isTopLevel() and getJsonFile().getBaseName().matches(".babelrc%")
|
||||
or
|
||||
this = any(PackageJSON pkg).getPropValue("babel")
|
||||
this = any(PackageJson pkg).getPropValue("babel")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuration for the plugin with the given name.
|
||||
*/
|
||||
JSONValue getPluginConfig(string pluginName) {
|
||||
exists(JSONArray plugins |
|
||||
JsonValue getPluginConfig(string pluginName) {
|
||||
exists(JsonArray plugins |
|
||||
plugins = getPropValue("plugins") and
|
||||
result = plugins.getElementValue(_)
|
||||
|
|
||||
@@ -38,7 +38,7 @@ module Babel {
|
||||
or
|
||||
result = getAContainerInScope().getAChildContainer() and
|
||||
// File-relative .babelrc search stops at any package.json or .babelrc file.
|
||||
not result.getAChildContainer() = any(PackageJSON pkg).getJsonFile() and
|
||||
not result.getAChildContainer() = any(PackageJson pkg).getJsonFile() and
|
||||
not result.getAChildContainer() = any(Config pkg).getJsonFile()
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ module Babel {
|
||||
/**
|
||||
* A configuration object for a Babel plugin.
|
||||
*/
|
||||
class Plugin extends JSONValue {
|
||||
class Plugin extends JsonValue {
|
||||
Config cfg;
|
||||
string pluginName;
|
||||
|
||||
@@ -64,10 +64,10 @@ module Babel {
|
||||
Config getConfig() { result = cfg }
|
||||
|
||||
/** Gets the options value passed to the plugin, if any. */
|
||||
JSONValue getOptions() { result = this.(JSONArray).getElementValue(1) }
|
||||
JsonValue getOptions() { result = this.(JsonArray).getElementValue(1) }
|
||||
|
||||
/** Gets a named option from the option object, if present. */
|
||||
JSONValue getOption(string name) { result = getOptions().getPropValue(name) }
|
||||
JsonValue getOption(string name) { result = getOptions().getPropValue(name) }
|
||||
|
||||
/** Holds if this plugin applies to `tl`. */
|
||||
predicate appliesTo(TopLevel tl) { cfg.appliesTo(tl) }
|
||||
@@ -99,12 +99,12 @@ module Babel {
|
||||
/**
|
||||
* Gets an object specifying a root prefix.
|
||||
*/
|
||||
private JSONObject getARootPathSpec() {
|
||||
private JsonObject getARootPathSpec() {
|
||||
// ["babel-plugin-root-import", <spec>]
|
||||
result = getOptions() and
|
||||
exists(result.getPropValue("rootPathSuffix"))
|
||||
or
|
||||
exists(JSONArray pathSpecs |
|
||||
exists(JsonArray pathSpecs |
|
||||
// ["babel-plugin-root-import", [ <spec>... ] ]
|
||||
pathSpecs = getOptions()
|
||||
or
|
||||
@@ -119,7 +119,7 @@ module Babel {
|
||||
* Gets the (explicitly specified) root for the given prefix.
|
||||
*/
|
||||
private string getExplicitRoot(string prefix) {
|
||||
exists(JSONObject rootPathSpec |
|
||||
exists(JsonObject rootPathSpec |
|
||||
rootPathSpec = getARootPathSpec() and
|
||||
result = rootPathSpec.getPropStringValue("rootPathSuffix")
|
||||
|
|
||||
@@ -140,7 +140,6 @@ module Babel {
|
||||
*/
|
||||
private class BabelRootTransformedPathExpr extends PathExpr, Expr {
|
||||
RootImportConfig plugin;
|
||||
string rawPath;
|
||||
string prefix;
|
||||
string mappedPrefix;
|
||||
string suffix;
|
||||
@@ -148,9 +147,8 @@ module Babel {
|
||||
BabelRootTransformedPathExpr() {
|
||||
this instanceof PathExpr and
|
||||
plugin.appliesTo(getTopLevel()) and
|
||||
rawPath = getStringValue() and
|
||||
prefix = rawPath.regexpCapture("(.)/(.*)", 1) and
|
||||
suffix = rawPath.regexpCapture("(.)/(.*)", 2) and
|
||||
prefix = getStringValue().regexpCapture("(.)/(.*)", 1) and
|
||||
suffix = getStringValue().regexpCapture("(.)/(.*)", 2) and
|
||||
mappedPrefix = plugin.getRoot(prefix)
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,6 @@ class ClientRequest extends DataFlow::InvokeNode instanceof ClientRequest::Range
|
||||
DataFlow::Node getASavePath() { result = super.getASavePath() }
|
||||
}
|
||||
|
||||
deprecated class CustomClientRequest = ClientRequest::Range;
|
||||
|
||||
module ClientRequest {
|
||||
/**
|
||||
* A call that performs a request to a URL.
|
||||
@@ -548,8 +546,8 @@ module ClientRequest {
|
||||
*
|
||||
* Note: Prefer to use the `ClientRequest` class as it is more general.
|
||||
*/
|
||||
class XMLHttpRequest extends ClientRequest::Range {
|
||||
XMLHttpRequest() {
|
||||
class XmlHttpRequest extends ClientRequest::Range {
|
||||
XmlHttpRequest() {
|
||||
this = DataFlow::globalVarRef("XMLHttpRequest").getAnInstantiation()
|
||||
or
|
||||
// closure shim for XMLHttpRequest
|
||||
@@ -620,6 +618,9 @@ module ClientRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for XmlHttpRequest */
|
||||
deprecated class XMLHttpRequest = XmlHttpRequest;
|
||||
|
||||
/**
|
||||
* A model of a URL request made using the `XhrIo` class from the closure library.
|
||||
*/
|
||||
@@ -790,8 +791,8 @@ module ClientRequest {
|
||||
/**
|
||||
* A model of a URL request made using `jsdom.fromUrl()`.
|
||||
*/
|
||||
class JSDOMFromUrl extends ClientRequest::Range {
|
||||
JSDOMFromUrl() {
|
||||
class JSDomFromUrl extends ClientRequest::Range {
|
||||
JSDomFromUrl() {
|
||||
this = API::moduleImport("jsdom").getMember("JSDOM").getMember("fromURL").getACall()
|
||||
}
|
||||
|
||||
@@ -802,6 +803,9 @@ module ClientRequest {
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JSDomFromUrl */
|
||||
deprecated class JSDOMFromUrl = JSDomFromUrl;
|
||||
|
||||
/**
|
||||
* Classes and predicates modeling the `apollo-client` library.
|
||||
*/
|
||||
|
||||
@@ -367,10 +367,10 @@ private module ExpressCookies {
|
||||
* In case an array is passed `setHeader("Set-Cookie", [...]` it sets multiple cookies.
|
||||
* We model a `CookieWrite` for each array element.
|
||||
*/
|
||||
private class HTTPCookieWrite extends CookieWrites::CookieWrite {
|
||||
private class HttpCookieWrite extends CookieWrites::CookieWrite {
|
||||
string header;
|
||||
|
||||
HTTPCookieWrite() {
|
||||
HttpCookieWrite() {
|
||||
exists(HTTP::CookieDefinition setCookie |
|
||||
this.asExpr() = setCookie.getHeaderArgument() and
|
||||
not this instanceof DataFlow::ArrayCreationNode
|
||||
|
||||
@@ -378,10 +378,9 @@ private module CryptoJS {
|
||||
* A model of the TweetNaCl library.
|
||||
*/
|
||||
private module TweetNaCl {
|
||||
private class Apply extends CryptographicOperation {
|
||||
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
|
||||
Expr input;
|
||||
CryptographicAlgorithm algorithm;
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
/*
|
||||
@@ -395,15 +394,14 @@ private module TweetNaCl {
|
||||
* Also matches the "hash" method name, and the "nacl-fast" module.
|
||||
*/
|
||||
|
||||
this = mce and
|
||||
exists(DataFlow::SourceNode mod, string name |
|
||||
name = "hash" and algorithm.matchesName("SHA512")
|
||||
or
|
||||
name = "sign" and algorithm.matchesName("ed25519")
|
||||
|
|
||||
(mod = DataFlow::moduleImport("nacl") or mod = DataFlow::moduleImport("nacl-fast")) and
|
||||
mce = mod.getAMemberCall(name).asExpr() and
|
||||
mce.getArgument(0) = input
|
||||
this = mod.getAMemberCall(name).asExpr() and
|
||||
super.getArgument(0) = input
|
||||
)
|
||||
}
|
||||
|
||||
@@ -440,10 +438,9 @@ private module HashJs {
|
||||
)
|
||||
}
|
||||
|
||||
private class Apply extends CryptographicOperation {
|
||||
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
|
||||
Expr input;
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
/*
|
||||
@@ -459,9 +456,8 @@ private module HashJs {
|
||||
* Also matches where `hash.<algorithmName>()` has been replaced by a more specific require a la `require("hash.js/lib/hash/sha/512")`
|
||||
*/
|
||||
|
||||
this = mce and
|
||||
mce = getAlgorithmExpr(algorithm).getAMemberCall("update").asExpr() and
|
||||
input = mce.getArgument(0)
|
||||
this = getAlgorithmExpr(algorithm).getAMemberCall("update").asExpr() and
|
||||
input = super.getArgument(0)
|
||||
}
|
||||
|
||||
override Expr getInput() { result = input }
|
||||
@@ -535,16 +531,14 @@ private module Forge {
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
}
|
||||
|
||||
private class Apply extends CryptographicOperation {
|
||||
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
|
||||
Expr input;
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
this = mce and
|
||||
exists(Cipher cipher |
|
||||
mce = cipher.getAMemberCall("update").asExpr() and
|
||||
mce.getArgument(0) = input and
|
||||
this = cipher.getAMemberCall("update").asExpr() and
|
||||
super.getArgument(0) = input and
|
||||
algorithm = cipher.getAlgorithm()
|
||||
)
|
||||
}
|
||||
@@ -596,19 +590,17 @@ private module Forge {
|
||||
* A model of the md5 library.
|
||||
*/
|
||||
private module Md5 {
|
||||
private class Apply extends CryptographicOperation {
|
||||
private class Apply extends CryptographicOperation instanceof CallExpr {
|
||||
Expr input;
|
||||
CryptographicAlgorithm algorithm;
|
||||
CallExpr call;
|
||||
|
||||
Apply() {
|
||||
// `require("md5")("message");`
|
||||
this = call and
|
||||
exists(DataFlow::SourceNode mod |
|
||||
mod = DataFlow::moduleImport("md5") and
|
||||
algorithm.matchesName("MD5") and
|
||||
call = mod.getACall().asExpr() and
|
||||
call.getArgument(0) = input
|
||||
this = mod.getACall().asExpr() and
|
||||
super.getArgument(0) = input
|
||||
)
|
||||
}
|
||||
|
||||
@@ -622,14 +614,12 @@ private module Md5 {
|
||||
* A model of the bcrypt, bcryptjs, bcrypt-nodejs libraries.
|
||||
*/
|
||||
private module Bcrypt {
|
||||
private class Apply extends CryptographicOperation {
|
||||
private class Apply extends CryptographicOperation instanceof MethodCallExpr {
|
||||
Expr input;
|
||||
CryptographicAlgorithm algorithm;
|
||||
MethodCallExpr mce;
|
||||
|
||||
Apply() {
|
||||
// `require("bcrypt").hash(password);` with minor naming variations
|
||||
this = mce and
|
||||
exists(DataFlow::SourceNode mod, string moduleName, string methodName |
|
||||
algorithm.matchesName("BCRYPT") and
|
||||
(
|
||||
@@ -642,8 +632,8 @@ private module Bcrypt {
|
||||
methodName = "hashSync"
|
||||
) and
|
||||
mod = DataFlow::moduleImport(moduleName) and
|
||||
mce = mod.getAMemberCall(methodName).asExpr() and
|
||||
mce.getArgument(0) = input
|
||||
this = mod.getAMemberCall(methodName).asExpr() and
|
||||
super.getArgument(0) = input
|
||||
)
|
||||
}
|
||||
|
||||
@@ -657,20 +647,18 @@ private module Bcrypt {
|
||||
* A model of the hasha library.
|
||||
*/
|
||||
private module Hasha {
|
||||
private class Apply extends CryptographicOperation {
|
||||
private class Apply extends CryptographicOperation instanceof CallExpr {
|
||||
Expr input;
|
||||
CryptographicAlgorithm algorithm;
|
||||
CallExpr call;
|
||||
|
||||
Apply() {
|
||||
// `require('hasha')('unicorn', { algorithm: "md5" });`
|
||||
this = call and
|
||||
exists(DataFlow::SourceNode mod, string algorithmName, Expr algorithmNameNode |
|
||||
mod = DataFlow::moduleImport("hasha") and
|
||||
call = mod.getACall().asExpr() and
|
||||
call.getArgument(0) = input and
|
||||
this = mod.getACall().asExpr() and
|
||||
super.getArgument(0) = input and
|
||||
algorithm.matchesName(algorithmName) and
|
||||
call.hasOptionArgument(1, "algorithm", algorithmNameNode) and
|
||||
super.hasOptionArgument(1, "algorithm", algorithmNameNode) and
|
||||
algorithmNameNode.mayHaveStringValue(algorithmName)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -189,8 +189,6 @@ module Electron {
|
||||
abstract class Range extends NodeJSLib::NodeJSClientRequest::Range { }
|
||||
}
|
||||
|
||||
deprecated class CustomElectronClientRequest = ElectronClientRequest::Range;
|
||||
|
||||
/**
|
||||
* A Node.js-style HTTP or HTTPS request made using `electron.ClientRequest`.
|
||||
*/
|
||||
|
||||
@@ -212,12 +212,12 @@ private class RecursiveReadDir extends FileSystemAccess, FileNameProducer, API::
|
||||
/**
|
||||
* Classes and predicates for modeling the `jsonfile` library (https://www.npmjs.com/package/jsonfile).
|
||||
*/
|
||||
private module JSONFile {
|
||||
private module JsonFile {
|
||||
/**
|
||||
* A reader for JSON files.
|
||||
*/
|
||||
class JSONFileReader extends FileSystemReadAccess, API::CallNode {
|
||||
JSONFileReader() {
|
||||
class JsonFileReader extends FileSystemReadAccess, API::CallNode {
|
||||
JsonFileReader() {
|
||||
this = API::moduleImport("jsonfile").getMember(["readFile", "readFileSync"]).getACall()
|
||||
}
|
||||
|
||||
@@ -238,11 +238,14 @@ private module JSONFile {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonFileReader */
|
||||
deprecated class JSONFileReader = JsonFileReader;
|
||||
|
||||
/**
|
||||
* A writer for JSON files.
|
||||
*/
|
||||
class JSONFileWriter extends FileSystemWriteAccess, DataFlow::CallNode {
|
||||
JSONFileWriter() {
|
||||
class JsonFileWriter extends FileSystemWriteAccess, DataFlow::CallNode {
|
||||
JsonFileWriter() {
|
||||
this =
|
||||
DataFlow::moduleMember("jsonfile", any(string s | s = "writeFile" or s = "writeFileSync"))
|
||||
.getACall()
|
||||
@@ -252,6 +255,9 @@ private module JSONFile {
|
||||
|
||||
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonFileWriter */
|
||||
deprecated class JSONFileWriter = JsonFileWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -104,13 +104,6 @@ module HTTP {
|
||||
predicate isUnsafe() { not this.isSafe() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `http` or `https` directly as appropriate.
|
||||
*
|
||||
* Gets the string `http` or `https`.
|
||||
*/
|
||||
deprecated string httpOrHttps() { result = "http" or result = "https" }
|
||||
|
||||
/**
|
||||
* An expression whose value is sent as (part of) the body of an HTTP response.
|
||||
*/
|
||||
@@ -411,10 +404,10 @@ module HTTP {
|
||||
* E.g. `chunk` in: `http.createServer().on('request', (req, res) => req.on("data", (chunk) => ...))`.
|
||||
*/
|
||||
private class ServerRequestDataEvent extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
RequestSource req;
|
||||
|
||||
ServerRequestDataEvent() {
|
||||
exists(DataFlow::MethodCallNode mcn | mcn = req.ref().getAMethodCall(EventEmitter::on()) |
|
||||
exists(DataFlow::MethodCallNode mcn, RequestSource req |
|
||||
mcn = req.ref().getAMethodCall(EventEmitter::on())
|
||||
|
|
||||
mcn.getArgument(0).mayHaveStringValue("data") and
|
||||
this = mcn.getABoundCallbackParameter(1, 0)
|
||||
)
|
||||
|
||||
@@ -74,12 +74,13 @@ private module HttpProxy {
|
||||
*/
|
||||
class ProxyListenerCallback extends NodeJSLib::RouteHandler, DataFlow::FunctionNode {
|
||||
string event;
|
||||
API::CallNode call;
|
||||
|
||||
ProxyListenerCallback() {
|
||||
call = any(CreateServerCall server).getReturn().getMember(["on", "once"]).getACall() and
|
||||
call.getParameter(0).getARhs().mayHaveStringValue(event) and
|
||||
this = call.getParameter(1).getARhs().getAFunctionValue()
|
||||
exists(API::CallNode call |
|
||||
call = any(CreateServerCall server).getReturn().getMember(["on", "once"]).getACall() and
|
||||
call.getParameter(0).getARhs().mayHaveStringValue(event) and
|
||||
this = call.getParameter(1).getARhs().getAFunctionValue()
|
||||
)
|
||||
}
|
||||
|
||||
override Parameter getRequestParameter() {
|
||||
|
||||
@@ -42,8 +42,8 @@ private module JsonWebToken {
|
||||
/**
|
||||
* The private key for a JWT as a `CredentialsExpr`.
|
||||
*/
|
||||
private class JWTKey extends CredentialsExpr {
|
||||
JWTKey() {
|
||||
private class JwtKey extends CredentialsExpr {
|
||||
JwtKey() {
|
||||
this = DataFlow::moduleMember("jsonwebtoken", "sign").getACall().getArgument(1).asExpr()
|
||||
}
|
||||
|
||||
|
||||
@@ -5,22 +5,6 @@
|
||||
import javascript
|
||||
|
||||
module LazyCache {
|
||||
/**
|
||||
* DEPRECATED. DO NOT USE.
|
||||
*
|
||||
* A lazy-cache object, usually created through an expression of form `require('lazy-cache')(require)`.
|
||||
*/
|
||||
deprecated class LazyCacheObject extends DataFlow::SourceNode {
|
||||
LazyCacheObject() {
|
||||
// Use `require` directly instead of `moduleImport` to avoid recursion.
|
||||
// For the same reason, avoid `Import.getImportedPath`.
|
||||
exists(Require req |
|
||||
req.getArgument(0).getStringValue() = "lazy-cache" and
|
||||
this = req.flow().(DataFlow::SourceNode).getAnInvocation()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable containing a lazy-cache object.
|
||||
*/
|
||||
|
||||
@@ -29,9 +29,9 @@ module LdapJS {
|
||||
|
||||
/** A reference to a LDAPjs client `search` options. */
|
||||
class SearchOptions extends API::Node {
|
||||
ClientCall call;
|
||||
|
||||
SearchOptions() { call.getMethodName() = "search" and this = call.getParameter(1) }
|
||||
SearchOptions() {
|
||||
exists(ClientCall call | call.getMethodName() = "search" and this = call.getParameter(1))
|
||||
}
|
||||
}
|
||||
|
||||
/** A creation of an LDAPjs filter, or object containing a filter, that doesn't sanitizes the input. */
|
||||
|
||||
@@ -123,7 +123,7 @@ private module Winston {
|
||||
/**
|
||||
* Provides classes for working with [log4js](https://github.com/log4js-node/log4js-node).
|
||||
*/
|
||||
private module log4js {
|
||||
private module Log4js {
|
||||
/**
|
||||
* A call to the log4js logging mechanism.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,10 @@ module Markdown {
|
||||
/**
|
||||
* Holds if the taint-step preserves HTML.
|
||||
*/
|
||||
predicate preservesHTML() { any() }
|
||||
predicate preservesHtml() { any() }
|
||||
|
||||
/** DEPRECATED: Alias for preservesHtml */
|
||||
deprecated predicate preservesHTML() { this.preservesHtml() }
|
||||
}
|
||||
|
||||
private class MarkdownStepAsTaintStep extends TaintTracking::SharedTaintStep {
|
||||
|
||||
@@ -376,11 +376,11 @@ module NestJS {
|
||||
* redirects to `https://example.com`.
|
||||
*/
|
||||
private class ReturnValueAsRedirection extends ServerSideUrlRedirect::Sink {
|
||||
NestJSRouteHandler handler;
|
||||
|
||||
ReturnValueAsRedirection() {
|
||||
handler.hasRedirectDecorator() and
|
||||
this = handler.getAReturn().getALocalSource().getAPropertyWrite("url").getRhs()
|
||||
exists(NestJSRouteHandler handler |
|
||||
handler.hasRedirectDecorator() and
|
||||
this = handler.getAReturn().getALocalSource().getAPropertyWrite("url").getRhs()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ module NextJS {
|
||||
/**
|
||||
* Gets a `package.json` that depends on the `Next.js` library.
|
||||
*/
|
||||
PackageJSON getANextPackage() { result.getDependencies().getADependency("next", _) }
|
||||
PackageJson getANextPackage() { result.getDependencies().getADependency("next", _) }
|
||||
|
||||
/**
|
||||
* Gets a "pages" folder in a `Next.js` application.
|
||||
@@ -155,11 +155,7 @@ module NextJS {
|
||||
* A Next.js function that is exected on the server for every request, seen as a routehandler.
|
||||
*/
|
||||
class NextHttpRouteHandler extends HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode {
|
||||
Module pageModule;
|
||||
|
||||
NextHttpRouteHandler() {
|
||||
this = getServerSidePropsFunction(pageModule) or this = getInitialProps(pageModule)
|
||||
}
|
||||
NextHttpRouteHandler() { this = getServerSidePropsFunction(_) or this = getInitialProps(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,9 +195,9 @@ module NextJS {
|
||||
* The response (res) includes a set of Express.js-like methods,
|
||||
* and we therefore model the routehandler as an Express.js routehandler.
|
||||
*/
|
||||
class NextAPIRouteHandler extends DataFlow::FunctionNode, Express::RouteHandler,
|
||||
class NextApiRouteHandler extends DataFlow::FunctionNode, Express::RouteHandler,
|
||||
HTTP::Servers::StandardRouteHandler {
|
||||
NextAPIRouteHandler() {
|
||||
NextApiRouteHandler() {
|
||||
exists(Module mod | mod.getFile().getParentContainer() = apiFolder() |
|
||||
this = mod.getAnExportedValue("default").getAFunctionValue()
|
||||
)
|
||||
@@ -214,6 +210,9 @@ module NextJS {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for NextApiRouteHandler */
|
||||
deprecated class NextAPIRouteHandler = NextApiRouteHandler;
|
||||
|
||||
/**
|
||||
* Gets a reference to a [Next.js router](https://nextjs.org/docs/api-reference/next/router).
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
import javascript
|
||||
import semmle.javascript.Promises
|
||||
|
||||
module NoSQL {
|
||||
/** Provices classes for modelling NoSQL query sinks. */
|
||||
module NoSql {
|
||||
/** An expression that is interpreted as a NoSQL query. */
|
||||
abstract class Query extends Expr {
|
||||
/** Gets an expression that is interpreted as a code operator in this query. */
|
||||
@@ -13,6 +14,9 @@ module NoSQL {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for NoSql */
|
||||
deprecated module NoSQL = NoSql;
|
||||
|
||||
/**
|
||||
* Gets a value that has been assigned to the "$where" property of an object that flows to `queryArg`.
|
||||
*/
|
||||
@@ -78,7 +82,7 @@ private module MongoDB {
|
||||
/**
|
||||
* An expression that is interpreted as a MongoDB query.
|
||||
*/
|
||||
class Query extends NoSQL::Query {
|
||||
class Query extends NoSql::Query {
|
||||
QueryCall qc;
|
||||
|
||||
Query() { this = qc.getAQueryArgument().asExpr() }
|
||||
@@ -512,7 +516,7 @@ private module Mongoose {
|
||||
/**
|
||||
* An expression that is interpreted as a (part of a) MongoDB query.
|
||||
*/
|
||||
class MongoDBQueryPart extends NoSQL::Query {
|
||||
class MongoDBQueryPart extends NoSql::Query {
|
||||
MongooseFunction f;
|
||||
|
||||
MongoDBQueryPart() { this = f.getQueryArgument().getARhs().asExpr() }
|
||||
@@ -619,7 +623,7 @@ private module Minimongo {
|
||||
/**
|
||||
* An expression that is interpreted as a Minimongo query.
|
||||
*/
|
||||
class Query extends NoSQL::Query {
|
||||
class Query extends NoSql::Query {
|
||||
QueryCall qc;
|
||||
|
||||
Query() { this = qc.getAQueryArgument().asExpr() }
|
||||
@@ -679,7 +683,7 @@ private module MarsDB {
|
||||
/**
|
||||
* An expression that is interpreted as a MarsDB query.
|
||||
*/
|
||||
class Query extends NoSQL::Query {
|
||||
class Query extends NoSql::Query {
|
||||
QueryCall qc;
|
||||
|
||||
Query() { this = qc.getAQueryArgument().asExpr() }
|
||||
@@ -763,7 +767,7 @@ private module Redis {
|
||||
/**
|
||||
* An expression that is interpreted as a key in a Node Redis call.
|
||||
*/
|
||||
class RedisKeyArgument extends NoSQL::Query {
|
||||
class RedisKeyArgument extends NoSql::Query {
|
||||
RedisKeyArgument() {
|
||||
exists(string method, int argIndex |
|
||||
QuerySignatures::argumentIsAmbiguousKey(method, argIndex) and
|
||||
|
||||
@@ -801,11 +801,6 @@ module NodeJSLib {
|
||||
TrackedRouteHandlerCandidateWithSetup() { this = any(RouteSetup s).getARouteHandler() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED Use `VmModuleMemberInvocation` instead.
|
||||
*/
|
||||
deprecated class VmModuleMethodCall = VmModuleMemberInvocation;
|
||||
|
||||
/**
|
||||
* An invocation of a member from module `vm`
|
||||
*/
|
||||
@@ -864,8 +859,6 @@ module NodeJSLib {
|
||||
abstract class Range extends ClientRequest::Range { }
|
||||
}
|
||||
|
||||
deprecated class CustomNodeJSClientRequest = NodeJSClientRequest::Range;
|
||||
|
||||
/**
|
||||
* A model of a URL request in the Node.js `http` library.
|
||||
*/
|
||||
@@ -1171,17 +1164,17 @@ module NodeJSLib {
|
||||
* A connection opened on a NodeJS net server.
|
||||
*/
|
||||
private class NodeJSNetServerConnection extends EventEmitter::Range {
|
||||
NodeJSNetServer server;
|
||||
|
||||
NodeJSNetServerConnection() {
|
||||
exists(DataFlow::MethodCallNode call |
|
||||
call = server.ref().getAMethodCall("on") and
|
||||
call.getArgument(0).mayHaveStringValue("connection")
|
||||
|
|
||||
this = call.getCallback(1).getParameter(0)
|
||||
exists(NodeJSNetServer server |
|
||||
exists(DataFlow::MethodCallNode call |
|
||||
call = server.ref().getAMethodCall("on") and
|
||||
call.getArgument(0).mayHaveStringValue("connection")
|
||||
|
|
||||
this = call.getCallback(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
this = server.getCallback([0, 1]).getParameter(0)
|
||||
)
|
||||
or
|
||||
this = server.getCallback([0, 1]).getParameter(0)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref() { result = EventEmitter::trackEventEmitter(this) }
|
||||
@@ -1201,9 +1194,9 @@ module NodeJSLib {
|
||||
* A data flow node representing data received from a client to a NodeJS net server, viewed as remote user input.
|
||||
*/
|
||||
private class NodeJSNetServerItemAsRemoteFlow extends RemoteFlowSource {
|
||||
NodeJSNetServerRegistration reg;
|
||||
|
||||
NodeJSNetServerItemAsRemoteFlow() { this = reg.getReceivedItem(_) }
|
||||
NodeJSNetServerItemAsRemoteFlow() {
|
||||
this = any(NodeJSNetServerRegistration reg).getReceivedItem(_)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "NodeJS server" }
|
||||
}
|
||||
|
||||
@@ -59,8 +59,6 @@ module PropertyProjection {
|
||||
}
|
||||
}
|
||||
|
||||
deprecated class CustomPropertyProjection = PropertyProjection::Range;
|
||||
|
||||
/**
|
||||
* Gets a callee of a simple property projection call.
|
||||
* This predicate is used exclusively in `SimplePropertyProjection`.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user