Merge remote-tracking branch 'upstream/main' into incomplete-url-string-sanitization

Conflicts:
	config/identical-files.json
	javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql
	javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll
	ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll
This commit is contained in:
Arthur Baars
2022-03-18 16:08:59 +01:00
1308 changed files with 77789 additions and 53601 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added sources from the [`jszip`](https://www.npmjs.com/package/jszip) library to the `js/zipslip` query.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,4 +0,0 @@
---
category: majorAnalysis
---
* Added support for TypeScript 4.6.

View 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.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.11
lastReleaseVersion: 0.0.12

View File

@@ -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

View File

@@ -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;

View File

@@ -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() }

View File

@@ -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) }

View File

@@ -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())
}
@@ -371,8 +371,12 @@ module API {
/**
* An API entry point.
*
* Extend this class to define additional API entry points other than modules.
* Typical examples include global variables.
* By default, API graph nodes are only created for nodes that come from an external
* library or escape into an external library. The points where values are cross the boundary
* between codebases are called "entry points".
*
* Imports and exports are considered entry points by default, but additional entry points may
* be added by extending this class. Typical examples include global variables.
*/
abstract class EntryPoint extends string {
bindingset[this]
@@ -385,7 +389,10 @@ module API {
abstract DataFlow::Node getARhs();
/** Gets an API-node for this entry point. */
API::Node getNode() { result = root().getASuccessor(Label::entryPoint(this)) }
API::Node getANode() { result = root().getASuccessor(Label::entryPoint(this)) }
/** DEPRECATED. Use `getANode()` instead. */
deprecated API::Node getNode() { result = this.getANode() }
}
/**
@@ -892,7 +899,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 +1258,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()

View File

@@ -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

View File

@@ -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()
}
}

View File

@@ -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.

View File

@@ -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
(

View File

@@ -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

View File

@@ -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

View File

@@ -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) }
}
/**

View File

@@ -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;
}

View File

@@ -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() }

View File

@@ -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

View File

@@ -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. */

View File

@@ -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()
)
}
}
}

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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 *&#47; }
* </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;

View File

@@ -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;

View File

@@ -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()
)

View File

@@ -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.

View File

@@ -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 }
}

View File

@@ -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
)

View File

@@ -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()
}
}

View File

@@ -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) }

View File

@@ -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))`

View File

@@ -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.
*
@@ -999,16 +990,22 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) {
}
/**
* Provides regular expression patterns.
* Provides utility predicates related to regular expressions.
*/
module RegExpPatterns {
/**
* Gets a pattern that matches common top-level domain names in lower case.
*/
string commonTLD() {
string getACommonTld() {
// according to ranking by http://google.com/search?q=site:.<<TLD>>
result = "(?:com|org|edu|gov|uk|net|io)(?![a-z0-9])"
}
/**
* Gets a pattern that matches common top-level domain names in lower case.
* DEPRECATED: use `getACommonTld` instead
*/
deprecated predicate commonTLD = getACommonTld/0;
}
/**
@@ -1300,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 = ["<", "'", "\""] }
}
/**

View File

@@ -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() }
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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, _, _, _))

View File

@@ -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.

View File

@@ -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() }
}
/**

View File

@@ -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;
}

View File

@@ -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.
*

View File

@@ -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

View File

@@ -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 }
}

View File

@@ -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)
}

View File

@@ -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)
)
}
}

View File

@@ -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() }
}

View File

@@ -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

View File

@@ -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)
)
}

View File

@@ -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() }
}
/**

View File

@@ -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

View File

@@ -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) {

View File

@@ -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() }

View File

@@ -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() }

View File

@@ -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.

View File

@@ -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(

View File

@@ -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()
}

View File

@@ -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)
}

View File

@@ -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.
*/

View File

@@ -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

View File

@@ -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)
)
}

View File

@@ -23,7 +23,7 @@ module D3 {
or
result = API::moduleImport("d3-node").getInstance().getMember("d3")
or
result = any(D3GlobalEntry i).getNode()
result = any(D3GlobalEntry i).getANode()
}
/**

View File

@@ -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`.
*/

View File

@@ -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;
}
/**

View File

@@ -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)
)

View File

@@ -17,7 +17,7 @@ module History {
* Gets a reference to the [`history`](https://npmjs.org/package/history) library.
*/
private API::Node history() {
result = [API::moduleImport("history"), any(HistoryGlobalEntry h).getNode()]
result = [API::moduleImport("history"), any(HistoryGlobalEntry h).getANode()]
}
/**

View File

@@ -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() {

View File

@@ -27,7 +27,7 @@ private module Immutable {
API::Node immutableImport() {
result = API::moduleImport("immutable")
or
result = any(ImmutableGlobalEntry i).getNode()
result = any(ImmutableGlobalEntry i).getANode()
}
/**

View File

@@ -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()
}

View File

@@ -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.
*/

View File

@@ -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. */

View File

@@ -45,7 +45,7 @@ private module Console {
*/
private API::Node console() {
result = API::moduleImport("console") or
result = any(ConsoleGlobalEntry e).getNode()
result = any(ConsoleGlobalEntry e).getANode()
}
/**
@@ -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.
*/

View File

@@ -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 {

View File

@@ -151,7 +151,7 @@ module NestJS {
private API::Node validationPipe() {
result = nestjs().getMember("ValidationPipe")
or
result = any(ValidationNodeEntry e).getNode()
result = any(ValidationNodeEntry e).getANode()
}
/**
@@ -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()
)
}
}

View File

@@ -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).
*/

View File

@@ -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

View File

@@ -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" }
}

View File

@@ -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`.

View File

@@ -23,7 +23,7 @@ DataFlow::SourceNode react() {
* - instances from `React.createClass`
* - stateless functional components
*/
abstract class ReactComponent extends ASTNode {
abstract class ReactComponent extends AstNode {
/**
* Gets an instance method of this component with the given name.
*/
@@ -208,7 +208,7 @@ abstract class ReactComponent extends ASTNode {
DataFlow::Node getACandidatePropsValue(string name) {
getACandidatePropsSource().hasPropertyWrite(name, result)
or
exists(ReactJSXElement e, JSXAttribute attr |
exists(ReactJsxElement e, JsxAttribute attr |
this = e.getComponent() and
attr = e.getAttributeByName(name) and
result.asExpr() = attr.getValue()
@@ -247,13 +247,13 @@ abstract class ReactComponent extends ASTNode {
/**
* Holds if `f` always returns a JSX element or fragment, or a React element.
*/
private predicate alwaysReturnsJSXOrReactElements(Function f) {
private predicate alwaysReturnsJsxOrReactElements(Function f) {
forex(Expr e |
e.flow().(DataFlow::SourceNode).flowsToExpr(f.getAReturnedExpr()) and
// Allow returning string constants in addition to JSX/React elemnts.
not exists(e.getStringValue())
|
e instanceof JSXNode or
e instanceof JsxNode or
e instanceof ReactElementDefinition
)
}
@@ -271,7 +271,7 @@ class FunctionalComponent extends ReactComponent, Function {
p.getName().regexpMatch("(?i).*props.*") or
p instanceof ObjectPattern
) and
alwaysReturnsJSXOrReactElements(this)
alwaysReturnsJsxOrReactElements(this)
}
override Function getInstanceMethod(string name) { name = "render" and result = this }
@@ -420,7 +420,7 @@ private class HeuristicReactPreactComponent extends ClassDefinition, PreactCompo
ES2015Component {
HeuristicReactPreactComponent() {
any(DataFlow::GlobalVarRefNode c | c.getName() = "Component").flowsToExpr(getSuperClass()) and
alwaysReturnsJSXOrReactElements(ClassDefinition.super.getInstanceMethod("render"))
alwaysReturnsJsxOrReactElements(ClassDefinition.super.getInstanceMethod("render"))
}
}
@@ -549,10 +549,10 @@ private class ReactCallbackPartialInvoke extends DataFlow::PartialInvokeNode::Ra
/**
* A `JSXElement` that instantiates a `ReactComponent`.
*/
private class ReactJSXElement extends JSXElement {
private class ReactJsxElement extends JsxElement {
ReactComponent component;
ReactJSXElement() { component.getAComponentCreatorReference().flowsToExpr(getNameExpr()) }
ReactJsxElement() { component.getAComponentCreatorReference().flowsToExpr(getNameExpr()) }
/**
* Gets the component this element instantiates.
@@ -646,7 +646,7 @@ private DataFlow::Node getAContextInput(DataFlow::CallNode createContext) {
createContext = react().getAMemberCall("createContext") and
result = createContext.getArgument(0) // initial value
or
exists(JSXElement provider |
exists(JsxElement provider |
getAContextRef(createContext)
.getAPropertyRead("Provider")
.flowsTo(provider.getNameExpr().flow()) and

View File

@@ -7,7 +7,7 @@ import javascript
module ReactNative {
/** A `WebView` JSX element. */
class WebViewElement extends DataFlow::ValueNode, DataFlow::SourceNode {
override JSXElement astNode;
override JsxElement astNode;
WebViewElement() {
DataFlow::moduleMember("react-native", "WebView").flowsToExpr(astNode.getNameExpr())

View File

@@ -16,19 +16,19 @@ module Redux {
*/
private module ProgramSlicing {
/** Gets the innermost `package.json` file in a directory containing the given file. */
private PackageJSON getPackageJson(Container f) {
private PackageJson getPackageJson(Container f) {
f = result.getFile().getParentContainer()
or
not exists(f.getFile("package.json")) and
result = getPackageJson(f.getParentContainer())
}
private predicate packageDependsOn(PackageJSON importer, PackageJSON dependency) {
private predicate packageDependsOn(PackageJson importer, PackageJson dependency) {
importer.getADependenciesObject("").getADependency(dependency.getPackageName(), _)
}
/** Gets a package that can be considered an entry point for a Redux app. */
private PackageJSON entryPointPackage() {
private PackageJson entryPointPackage() {
result = getPackageJson(any(StoreCreation c).getFile())
or
// Any package that imports a store-creating package is considered a potential entry point.
@@ -36,8 +36,8 @@ module Redux {
}
pragma[nomagic]
private predicate arePackagesInSameReduxApp(PackageJSON a, PackageJSON b) {
exists(PackageJSON entry |
private predicate arePackagesInSameReduxApp(PackageJson a, PackageJson b) {
exists(PackageJson entry |
entry = entryPointPackage() and
packageDependsOn*(entry, a) and
packageDependsOn*(entry, b)
@@ -47,7 +47,7 @@ module Redux {
/** Holds if the two files are considered to be part of the same Redux app. */
pragma[inline]
predicate areFilesInSameReduxApp(File a, File b) {
not exists(PackageJSON pkg)
not exists(PackageJson pkg)
or
arePackagesInSameReduxApp(getPackageJson(a), getPackageJson(b))
}
@@ -1111,7 +1111,7 @@ module Redux {
/** A heuristic call to `connect`, recognized by it taking arguments named `mapStateToProps` and `mapDispatchToProps`. */
private class HeuristicConnectFunction extends ConnectCall {
HeuristicConnectFunction() { this = any(HeuristicConnectEntryPoint e).getNode().getACall() }
HeuristicConnectFunction() { this = any(HeuristicConnectEntryPoint e).getANode().getACall() }
override API::Node getMapStateToProps() {
result = getAParameter() and

View File

@@ -82,11 +82,6 @@ module SocketIO {
}
override DataFlow::SourceNode ref() { result = this.server().getAUse() }
/**
* DEPRECATED. Always returns `this` as a `ServerObject` now represents the origin of a server.
*/
deprecated DataFlow::SourceNode getOrigin() { result = this }
}
/** A data flow node that may produce (that is, create or return) a socket.io server. */
@@ -523,7 +518,7 @@ module SocketIOClient {
}
/** Gets the NPM package that contains `nd`. */
private NPMPackage getPackage(DataFlow::SourceNode nd) { result.getAFile() = nd.getFile() }
private NpmPackage getPackage(DataFlow::SourceNode nd) { result.getAFile() = nd.getFile() }
/**
* A data flow node representing an API call that receives data from the server.

View File

@@ -84,7 +84,7 @@ module Templating {
predicate isInCodeAttribute() {
exists(TopLevel code | code = this.getParent().(HTML::Attribute).getCodeInAttribute() |
code instanceof EventHandlerCode or
code instanceof JavaScriptURL
code instanceof JavaScriptUrl
)
}

View File

@@ -39,12 +39,14 @@ class BDDTest extends Test, @call_expr {
}
/**
* Gets the test file for `f` with stem extension `stemExt`.
* That is, a file named file named `<base>.<stemExt>.<ext>` in the
* Gets the test file for `f` with stem extension `stemExt`, where `stemExt` is "test" or "spec".
* That is, a file named `<base>.<stemExt>.<ext>` in the
* same directory as `f` which is named `<base>.<ext>`.
*/
bindingset[stemExt]
pragma[noinline]
File getTestFile(File f, string stemExt) {
stemExt = ["test", "spec"] and
result.getBaseName().regexpMatch(".*\\.(test|spec)\\..*") and
result = f.getParentContainer().getFile(f.getStem() + "." + stemExt + "." + f.getExtension())
}

View File

@@ -19,7 +19,7 @@ module TrustedTypes {
override DataFlow::Node getARhs() { none() }
}
private API::Node trustedTypesObj() { result = any(TrustedTypesEntry entry).getNode() }
private API::Node trustedTypesObj() { result = any(TrustedTypesEntry entry).getANode() }
/** A call to `trustedTypes.createPolicy`. */
class PolicyCreation extends API::CallNode {

View File

@@ -14,10 +14,13 @@ abstract deprecated class UriLibraryStep extends DataFlow::ValueNode {
predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
}
/** DEPRECATED: Alias for `Urijs` */
deprecated module urijs = Urijs;
/**
* Provides classes for working with [urijs](http://medialize.github.io/URI.js/) code.
*/
module urijs {
module Urijs {
/**
* Gets a data flow source node for the urijs library.
*/
@@ -80,10 +83,13 @@ module urijs {
}
}
/** DEPRECATED: Alias for `Uridashjs` */
deprecated module uridashjs = Uridashjs;
/**
* Provides classes for working with [uri-js](https://github.com/garycourt/uri-js) code.
*/
module uridashjs {
module Uridashjs {
/**
* Gets a data flow source node for member `name` of the uridashjs library.
*/
@@ -105,10 +111,13 @@ module uridashjs {
}
}
/** DEPRECATED: Alias for `Punycode` */
deprecated module punycode = Punycode;
/**
* Provides classes for working with [punycode](https://github.com/bestiejs/punycode.js) code.
*/
module punycode {
module Punycode {
/**
* Gets a data flow source node for member `name` of the punycode library.
*/
@@ -130,10 +139,13 @@ module punycode {
}
}
/** DEPRECATED: Alias for `UrlParse` */
deprecated module urlParse = UrlParse;
/**
* Provides classes for working with [url-parse](https://github.com/unshiftio/url-parse) code.
*/
module urlParse {
module UrlParse {
/**
* Gets a data flow source node for the url-parse library.
*/
@@ -167,10 +179,13 @@ module urlParse {
}
}
/** DEPRECATED: Alias for `Querystringify` */
deprecated module querystringify = Querystringify;
/**
* Provides classes for working with [querystringify](https://github.com/unshiftio/querystringify) code.
*/
module querystringify {
module Querystringify {
/**
* Gets a data flow source node for member `name` of the querystringify library.
*/
@@ -197,10 +212,13 @@ module querystringify {
}
}
/** DEPRECATED: Alias for `Querydashstring` */
deprecated module querydashstring = Querydashstring;
/**
* Provides classes for working with [query-string](https://github.com/sindresorhus/query-string) code.
*/
module querydashstring {
module Querydashstring {
/**
* Gets a data flow source node for member `name` of the query-string library.
*/
@@ -222,10 +240,13 @@ module querydashstring {
}
}
/** DEPRECATED: Alias for `Url` */
deprecated module url = Url;
/**
* Provides classes for working with [url](https://nodejs.org/api/url.html) code.
*/
module url {
module Url {
/**
* Gets a data flow source node for member `name` of the url library.
*/
@@ -245,10 +266,13 @@ module url {
}
}
/** DEPRECATED: Alias for `Querystring` */
deprecated module querystring = Querystring;
/**
* Provides classes for working with [querystring](https://nodejs.org/api/querystring.html) code.
*/
module querystring {
module Querystring {
/**
* Gets a data flow source node for member `name` of the querystring library.
*/
@@ -408,7 +432,7 @@ private module ClosureLibraryUri {
/**
* Provides classes for working with [path](https://nodejs.org/api/path.html) code.
*/
module path {
module Path {
/**
* A taint step in the path module.
*/

View File

@@ -35,7 +35,7 @@ module Vue {
API::Node vueLibrary() {
result = API::moduleImport("vue")
or
result = any(GlobalVueEntryPoint e).getNode()
result = any(GlobalVueEntryPoint e).getANode()
}
/**
@@ -51,7 +51,7 @@ module Vue {
or
result = vueLibrary().getMember("component").getReturn()
or
result = any(VueFileImportEntryPoint e).getNode()
result = any(VueFileImportEntryPoint e).getANode()
}
/**

View File

@@ -365,19 +365,19 @@ module Vuex {
*/
private module ProgramSlicing {
/** Gets the innermost `package.json` file in a directory containing the given file. */
private PackageJSON getPackageJson(Container f) {
private PackageJson getPackageJson(Container f) {
f = result.getFile().getParentContainer()
or
not exists(f.getFile("package.json")) and
result = getPackageJson(f.getParentContainer())
}
private predicate packageDependsOn(PackageJSON importer, PackageJSON dependency) {
private predicate packageDependsOn(PackageJson importer, PackageJson dependency) {
importer.getADependenciesObject("").getADependency(dependency.getPackageName(), _)
}
/** Gets a package that can be considered an entry point for a Vuex app. */
private PackageJSON entryPointPackage() {
private PackageJson entryPointPackage() {
result = getPackageJson(storeRef().getAnImmediateUse().getFile())
or
// Any package that imports a store-creating package is considered a potential entry point.
@@ -385,8 +385,8 @@ module Vuex {
}
pragma[nomagic]
private predicate arePackagesInSameVuexApp(PackageJSON a, PackageJSON b) {
exists(PackageJSON entry |
private predicate arePackagesInSameVuexApp(PackageJson a, PackageJson b) {
exists(PackageJson entry |
entry = entryPointPackage() and
packageDependsOn*(entry, a) and
packageDependsOn*(entry, b)
@@ -396,7 +396,7 @@ module Vuex {
/** Holds if the two files are considered to be part of the same Vuex app. */
pragma[inline]
predicate areFilesInSameVuexApp(File a, File b) {
not exists(PackageJSON pkg)
not exists(PackageJson pkg)
or
arePackagesInSameVuexApp(getPackageJson(a), getPackageJson(b))
}

View File

@@ -235,19 +235,22 @@ module ServerWebSocket {
/**
* The `req` parameter of a `socket.on("connection", (msg, req) => {})` call.
*/
class ServerHTTPRequest extends HTTP::Servers::RequestSource {
class ServerHttpRequest extends HTTP::Servers::RequestSource {
ConnectionCallAsRouteHandler handler;
ServerHTTPRequest() { this = handler.getCallback(1).getParameter(1) }
ServerHttpRequest() { this = handler.getCallback(1).getParameter(1) }
override HTTP::RouteHandler getRouteHandler() { result = handler }
}
/** DEPRECATED: Alias for ServerHttpRequest */
deprecated class ServerHTTPRequest = ServerHttpRequest;
/**
* An access user-controlled HTTP request input in a request to a WebSocket server.
*/
class WebSocketRequestInput extends HTTP::RequestInputAccess {
ServerHTTPRequest request;
ServerHttpRequest request;
string kind;
WebSocketRequestInput() {

View File

@@ -2,9 +2,9 @@
* Provides classes for working with XML parser APIs.
*/
private import javascript as js
private import js::DataFlow as DataFlow
private import js::API as API
private import javascript as JS
private import JS::DataFlow as DataFlow
private import JS::API as API
module XML {
/**
@@ -21,9 +21,9 @@ module XML {
/**
* A call to an XML parsing function.
*/
abstract class ParserInvocation extends js::InvokeExpr {
abstract class ParserInvocation extends JS::InvokeExpr {
/** Gets an argument to this call that is parsed as XML. */
abstract js::Expr getSourceArgument();
abstract JS::Expr getSourceArgument();
/** Holds if this call to the XML parser resolves entities of the given `kind`. */
abstract predicate resolvesEntities(EntityKind kind);
@@ -46,14 +46,14 @@ module XML {
)
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(EntityKind kind) {
// internal entities are always resolved
kind = InternalEntity()
or
// other entities are only resolved if the configuration option `noent` is set to `true`
exists(js::Expr noent |
exists(JS::Expr noent |
hasOptionArgument(1, "noent", noent) and
noent.mayHaveBooleanValue(true)
)
@@ -121,7 +121,7 @@ module XML {
this = parser.getMember("parseString").getACall().asExpr()
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(EntityKind kind) {
// entities are resolved by default
@@ -144,7 +144,7 @@ module XML {
this = parser.getMember("push").getACall().asExpr()
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(EntityKind kind) {
// entities are resolved by default
@@ -167,7 +167,7 @@ module XML {
this = parser.getMember(["parse", "write"]).getACall().asExpr()
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(EntityKind kind) {
// only internal entities are resolved by default
@@ -182,8 +182,8 @@ module XML {
/**
* An invocation of `DOMParser.parseFromString`.
*/
private class DOMParserXmlParserInvocation extends XML::ParserInvocation {
DOMParserXmlParserInvocation() {
private class DomParserXmlParserInvocation extends XML::ParserInvocation {
DomParserXmlParserInvocation() {
this =
DataFlow::globalVarRef("DOMParser")
.getAnInstantiation()
@@ -193,7 +193,7 @@ module XML {
getArgument(1).mayHaveStringValue(any(string tp | tp.matches("%xml%")))
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
@@ -215,7 +215,7 @@ module XML {
)
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { any() }
}
@@ -225,10 +225,10 @@ module XML {
*/
private class GoogDomXmlParserInvocation extends XML::ParserInvocation {
GoogDomXmlParserInvocation() {
this.getCallee().(js::PropAccess).getQualifiedName() = "goog.dom.xml.loadXml"
this.getCallee().(JS::PropAccess).getQualifiedName() = "goog.dom.xml.loadXml"
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
}
@@ -246,7 +246,7 @@ module XML {
)
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) {
// sax-js (the parser used) does not expand entities.
@@ -273,7 +273,7 @@ module XML {
this = parser.getAMemberCall("write").asExpr()
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) {
// sax-js does not expand entities.
@@ -302,7 +302,7 @@ module XML {
.asExpr()
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) {
// xml-js does not expand custom entities.
@@ -323,7 +323,7 @@ module XML {
this = parser.getReturn().getMember("write").getACall().asExpr()
}
override js::Expr getSourceArgument() { result = getArgument(0) }
override JS::Expr getSourceArgument() { result = getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) {
// htmlparser2 does not expand entities.
@@ -341,7 +341,7 @@ module XML {
}
}
private class XMLParserTaintStep extends js::TaintTracking::SharedTaintStep {
private class XmlParserTaintStep extends JS::TaintTracking::SharedTaintStep {
override predicate deserializeStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(XML::ParserInvocation parser |
pred.asExpr() = parser.getSourceArgument() and

View File

@@ -8,10 +8,6 @@
* The package name refers to an NPM package name or a path within a package name such as `lodash/extend`.
* The string `global` refers to the global object (whether it came from the `global` package or not).
*
* The following tokens have a language-specific interpretation:
* - `Instance`: the value returned by a `new`-call to a function
* - `Awaited`: the value from a resolved promise
*
* A `(package, type)` tuple may refer to the exported type named `type` from the NPM package `package`.
* For example, `(express, Request)` would match a parameter below due to the type annotation:
* ```ts

View File

@@ -22,16 +22,26 @@
* or the empty string if referring to the package itself.
* It can also be a synthetic type name defined by a type definition (see type definitions below).
* 3. The `path` column is a `.`-separated list of "access path tokens" to resolve, starting at the node selected by `package` and `type`.
* The possible access path tokens are:
* - Member[x] : a property named `x`. May be a comma-separated list of named.
*
* Every language supports the following tokens:
* - Argument[n]: the n-th argument to a call. May be a range of form `x..y` (inclusive) and/or a comma-separated list.
* Additionally, `N-1` refers to the last argument, `N-2` refers to the second-last, and so on.
* - Parameter[n]: the n-th parameter of a callback. May be a range of form `x..y` (inclusive) and/or a comma-separated list.
* - ReturnValue: the value returned by a function call
* - Instance: the value returned by a constructor call
* - Awaited: the value from a resolved promise/future-like object
* - WithArity[n]: match a call with the given arity. May be a range of form `x..y` (inclusive) and/or a comma-separated list.
* - Other language-specific tokens mentioned in `ModelsAsData.qll`.
*
* The following tokens are common and should be implemented for languages where it makes sense:
* - Member[x]: a member named `x`; exactly what a "member" is depends on the language. May be a comma-separated list of names.
* - Instance: an instance of a class
* - Subclass: a subclass of a class
* - ArrayElement: an element of array
* - Element: an element of a collection-like object
* - MapKey: a key in map-like object
* - MapValue: a value in a map-like object
* - Awaited: the value from a resolved promise/future-like object
*
* For the time being, please consult `ApiGraphModelsSpecific.qll` to see which language-specific tokens are currently supported.
*
* 4. The `input` and `output` columns specify how data enters and leaves the element selected by the
* first `(package, type, path)` tuple. Both strings are `.`-separated access paths
* of the same syntax as the `path` column.
@@ -149,6 +159,14 @@ module ModelInput {
private import ModelInput
/**
* An empty class, except in specific tests.
*
* If this is non-empty, all models are parsed even if the package is not
* considered relevant for the current database.
*/
abstract class TestAllModels extends Unit { }
/**
* Append `;dummy` to the value of `s` to work around the fact that `string.split(delim,n)`
* does not preserve empty trailing substrings.
@@ -231,7 +249,17 @@ string getAPackageAlias(string package) {
* Holds if CSV rows involving `package` might be relevant for the analysis of this database.
*/
private predicate isRelevantPackage(string package) {
Specific::isPackageUsed(package)
(
sourceModel(package, _, _, _) or
sinkModel(package, _, _, _) or
summaryModel(package, _, _, _, _, _) or
typeModel(package, _, _, _, _)
) and
(
Specific::isPackageUsed(package)
or
exists(TestAllModels t)
)
or
exists(string other |
isRelevantPackage(other) and
@@ -315,7 +343,7 @@ private predicate invocationMatchesCallSiteFilter(Specific::InvokeNode invoke, A
* Gets the API node identified by the first `n` tokens of `path` in the given `(package, type, path)` tuple.
*/
pragma[nomagic]
API::Node getNodeFromPath(string package, string type, AccessPath path, int n) {
private API::Node getNodeFromPath(string package, string type, AccessPath path, int n) {
isRelevantFullPath(package, type, path) and
(
n = 0 and
@@ -357,6 +385,42 @@ Specific::InvokeNode getInvocationFromPath(string package, string type, AccessPa
result = getInvocationFromPath(package, type, path, path.getNumToken())
}
/**
* Holds if `name` is a valid name for an access path token in the identifying access path.
*/
bindingset[name]
predicate isValidTokenNameInIdentifyingAccessPath(string name) {
name = ["Argument", "Parameter", "ReturnValue", "WithArity"]
or
Specific::isExtraValidTokenNameInIdentifyingAccessPath(name)
}
/**
* Holds if `name` is a valid name for an access path token with no arguments, occuring
* in an identifying access path.
*/
bindingset[name]
predicate isValidNoArgumentTokenInIdentifyingAccessPath(string name) {
name = "ReturnValue"
or
Specific::isExtraValidNoArgumentTokenInIdentifyingAccessPath(name)
}
/**
* Holds if `argument` is a valid argument to an access path token with the given `name`, occurring
* in an identifying access path.
*/
bindingset[name, argument]
predicate isValidTokenArgumentInIdentifyingAccessPath(string name, string argument) {
name = ["Argument", "Parameter"] and
argument.regexpMatch("(N-|-)?\\d+(\\.\\.(N-|-)?\\d+)?")
or
name = "WithArity" and
argument.regexpMatch("\\d+(\\.\\.\\d+)?")
or
Specific::isExtraValidTokenArgumentInIdentifyingAccessPath(name, argument)
}
/**
* Module providing access to the imported models in terms of API graph nodes.
*/
@@ -382,26 +446,23 @@ module ModelOutput {
}
/**
* Holds if a relevant CSV summary row has the given `kind`, `input` and `output`.
* Holds if a relevant CSV summary exists for these parameters.
*/
predicate summaryModel(string input, string output, string kind) {
exists(string package |
isRelevantPackage(package) and
summaryModel(package, _, _, input, output, kind)
)
predicate relevantSummaryModel(
string package, string type, string path, string input, string output, string kind
) {
isRelevantPackage(package) and
summaryModel(package, type, path, input, output, kind)
}
/**
* Holds if a summary edge with the given `input, output, kind` columns have a `package, type, path` tuple
* that resolves to `baseNode`.
* Holds if a `baseNode` is an invocation identified by the `package,type,path` part of a summary row.
*/
predicate resolvedSummaryBase(
Specific::InvokeNode baseNode, AccessPath input, AccessPath output, string kind
string package, string type, string path, Specific::InvokeNode baseNode
) {
exists(string package, string type, AccessPath path |
summaryModel(package, type, path, input, output, kind) and
baseNode = getInvocationFromPath(package, type, path)
)
summaryModel(package, type, path, _, _, _) and
baseNode = getInvocationFromPath(package, type, path)
}
/**
@@ -414,4 +475,48 @@ module ModelOutput {
result = getNodeFromPath(package2, type2, path)
)
}
/**
* Gets an error message relating to an invalid CSV row in a model.
*/
string getAWarning() {
// Check number of columns
exists(string row, string kind, int expectedArity, int actualArity |
any(SourceModelCsv csv).row(row) and kind = "source" and expectedArity = 4
or
any(SinkModelCsv csv).row(row) and kind = "sink" and expectedArity = 4
or
any(SummaryModelCsv csv).row(row) and kind = "summary" and expectedArity = 6
or
any(TypeModelCsv csv).row(row) and kind = "type" and expectedArity = 5
|
actualArity = count(row.indexOf(";")) + 1 and
actualArity != expectedArity and
result =
"CSV " + kind + " row should have " + expectedArity + " columns but has " + actualArity +
": " + row
)
or
// Check names and arguments of access path tokens
exists(AccessPath path, AccessPathToken token |
isRelevantFullPath(_, _, path) and
token = path.getToken(_)
|
not isValidTokenNameInIdentifyingAccessPath(token.getName()) and
result = "Invalid token name '" + token.getName() + "' in access path: " + path
or
isValidTokenNameInIdentifyingAccessPath(token.getName()) and
exists(string argument |
argument = token.getAnArgument() and
not isValidTokenArgumentInIdentifyingAccessPath(token.getName(), argument) and
result =
"Invalid argument '" + argument + "' in token '" + token + "' in access path: " + path
)
or
isValidTokenNameInIdentifyingAccessPath(token.getName()) and
token.getNumArgument() = 0 and
not isValidNoArgumentTokenInIdentifyingAccessPath(token.getName()) and
result = "Invalid token '" + token + "' is missing its arguments, in access path: " + path
)
}
}

View File

@@ -2,7 +2,7 @@
* Contains the language-specific part of the models-as-data implementation found in `ApiGraphModels.qll`.
*
* It must export the following members:
* ```codeql
* ```ql
* class Unit // a unit type
* module API // the API graph module
* predicate isPackageUsed(string package)
@@ -13,13 +13,14 @@
* ```
*/
private import javascript as js
private import js::DataFlow as DataFlow
private import javascript as JS
private import JS::DataFlow as DataFlow
private import ApiGraphModels
class Unit = js::Unit;
class Unit = JS::Unit;
module API = js::API;
// Re-export libraries needed by ApiGraphModels.qll
module API = JS::API;
import semmle.javascript.frameworks.data.internal.AccessPathSyntax as AccessPathSyntax
private import AccessPathSyntax
@@ -66,7 +67,7 @@ private class GlobalApiEntryPoint extends API::EntryPoint {
* Gets an API node referring to the given global variable (if relevant).
*/
private API::Node getGlobalNode(string globalName) {
result = any(GlobalApiEntryPoint e | e.getGlobal() = globalName).getNode()
result = any(GlobalApiEntryPoint e | e.getGlobal() = globalName).getANode()
}
/** Gets a JavaScript-specific interpretation of the `(package, type, path)` tuple after resolving the first `n` access path tokens. */
@@ -147,10 +148,12 @@ predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPat
* Holds if `path` is an input or output spec for a summary with the given `base` node.
*/
pragma[nomagic]
private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath path) {
ModelOutput::resolvedSummaryBase(base, path, _, _)
or
ModelOutput::resolvedSummaryBase(base, _, path, _)
private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath inputOrOutput) {
exists(string package, string type, string input, string output, string path |
ModelOutput::relevantSummaryModel(package, type, path, input, output, _) and
ModelOutput::resolvedSummaryBase(package, type, path, base) and
inputOrOutput = [input, output]
)
}
/**
@@ -178,8 +181,12 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat
* Holds if a CSV summary contributed the step `pred -> succ` of the given `kind`.
*/
predicate summaryStep(API::Node pred, API::Node succ, string kind) {
exists(API::InvokeNode base, AccessPath input, AccessPath output |
ModelOutput::resolvedSummaryBase(base, input, output, kind) and
exists(
string package, string type, string path, API::InvokeNode base, AccessPath input,
AccessPath output
|
ModelOutput::relevantSummaryModel(package, type, path, input, output, kind) and
ModelOutput::resolvedSummaryBase(package, type, path, base) and
pred = getNodeFromInputOutputPath(base, input) and
succ = getNodeFromInputOutputPath(base, output)
)
@@ -189,3 +196,29 @@ class InvokeNode = API::InvokeNode;
/** Gets an `InvokeNode` corresponding to an invocation of `node`. */
InvokeNode getAnInvocationOf(API::Node node) { result = node.getAnInvocation() }
/**
* Holds if `name` is a valid name for an access path token in the identifying access path.
*/
bindingset[name]
predicate isExtraValidTokenNameInIdentifyingAccessPath(string name) {
name = ["Member", "Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call"]
}
/**
* Holds if `name` is a valid name for an access path token with no arguments, occuring
* in an identifying access path.
*/
predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name) {
name = ["Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call"]
}
/**
* Holds if `argument` is a valid argument to an access path token with the given `name`, occurring
* in an identifying access path.
*/
bindingset[name, argument]
predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string argument) {
name = ["Member"] and
exists(argument)
}

View File

@@ -9,18 +9,6 @@ import javascript
*/
predicate jquery = JQuery::dollar/0;
/**
* DEPRECATED. In most cases, `JQuery::Object` should be used instead.
* Alternatively, if used as a base class, and the intent is to extend the model of
* jQuery objects with more nodes, extend `JQuery::ObjectSource::Range` instead.
*
* An expression that may refer to a jQuery object.
*
* Note that this class is an over-approximation: `nd instanceof JQueryObject`
* may hold for nodes `nd` that cannot, in fact, refer to a jQuery object.
*/
deprecated class JQueryObject = JQueryObjectInternal;
/**
* An internal version of `JQueryObject` that may be used to retain
* backwards compatibility without triggering a deprecation warning.
@@ -80,44 +68,6 @@ private predicate neverReturnsJQuery(string name) {
)
}
/**
* DEPRECATED. Use `JQuery::MethodCall` instead.
*
* A (possibly chained) call to a jQuery method.
*/
deprecated class JQueryMethodCall extends CallExpr {
string name;
JQueryMethodCall() { name = this.flow().(JQuery::MethodCall).getMethodName() }
/**
* Gets the name of the jQuery method this call invokes.
*/
string getMethodName() { result = name }
/**
* Holds if `e` is an argument that this method may interpret as HTML.
*
* Note that some jQuery methods decide whether to interpret an argument
* as HTML based on its syntactic shape, so this predicate and
* `interpretsArgumentAsSelector` below overlap.
*/
predicate interpretsArgumentAsHtml(Expr e) {
this.flow().(JQuery::MethodCall).interpretsArgumentAsHtml(e.flow())
}
/**
* Holds if `e` is an argument that this method may interpret as a selector.
*
* Note that some jQuery methods decide whether to interpret an argument
* as a selector based on its syntactic shape, so this predicate and
* `interpretsArgumentAsHtml` above overlap.
*/
predicate interpretsArgumentAsSelector(Expr e) {
this.flow().(JQuery::MethodCall).interpretsArgumentAsSelector(e.flow())
}
}
/**
* A call to `jQuery.parseXML`.
*/
@@ -284,10 +234,8 @@ private class JQueryAttr3Call extends JQueryAttributeDefinition, @call_expr {
* the DOM element constructed by `$("<script/>")`.
*/
private class JQueryChainedElement extends DOM::Element, InvokeExpr {
DOM::Element inner;
JQueryChainedElement() {
exists(JQuery::MethodCall call | this = call.asExpr() |
exists(JQuery::MethodCall call, DOM::Element inner | this = call.asExpr() |
call.getReceiver().asExpr() = inner and
defn = inner.getDefinition()
)

Some files were not shown because too many files have changed in this diff Show More