mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
convert the AngularJS model to use DataFlow nodes
This commit is contained in:
committed by
erik-krogh
parent
9bea110d24
commit
aa9261f1b1
@@ -167,7 +167,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
|
||||
/**
|
||||
* Holds if this expression may refer to the initial value of parameter `p`.
|
||||
*/
|
||||
predicate mayReferToParameter(Parameter p) { this.flow().mayReferToParameter(p) }
|
||||
predicate mayReferToParameter(Parameter p) { DataFlow::parameterNode(p).flowsToExpr(this) }
|
||||
|
||||
/**
|
||||
* Gets the static type of this expression, as determined by the TypeScript type system.
|
||||
|
||||
@@ -139,9 +139,12 @@ module DataFlow {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `DataFlow::ParameterNode::flowsTo()` instead.
|
||||
* Holds if this expression may refer to the initial value of parameter `p`.
|
||||
*/
|
||||
predicate mayReferToParameter(Parameter p) { parameterNode(p).(SourceNode).flowsTo(this) }
|
||||
deprecated predicate mayReferToParameter(Parameter p) {
|
||||
parameterNode(p).(SourceNode).flowsTo(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
|
||||
@@ -472,6 +472,12 @@ class FunctionNode extends DataFlow::ValueNode, DataFlow::SourceNode {
|
||||
/** Gets a parameter of this function. */
|
||||
ParameterNode getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets the parameter named `name` of this function, if any. */
|
||||
DataFlow::ParameterNode getParameterByName(string name) {
|
||||
result = getAParameter() and
|
||||
result.getName() = name
|
||||
}
|
||||
|
||||
/** Gets the number of parameters declared on this function. */
|
||||
int getNumParameter() { result = count(astNode.getAParameter()) }
|
||||
|
||||
|
||||
@@ -105,8 +105,8 @@ class AngularModule extends TAngularModule {
|
||||
/**
|
||||
* Get the array of dependencies from this module's definition.
|
||||
*/
|
||||
ArrayExpr getDependencyArray() {
|
||||
this.getADefinition().getArgument(1).getALocalSource().asExpr() = result
|
||||
DataFlow::ArrayCreationNode getDependencyArray() {
|
||||
this.getADefinition().getArgument(1).getALocalSource() = result
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,14 +160,10 @@ class ModuleApiCall extends DataFlow::CallNode {
|
||||
string getMethodName() { result = methodName }
|
||||
}
|
||||
|
||||
class ModuleApiCallDependencyInjection extends DependencyInjection {
|
||||
ModuleApiCall call;
|
||||
class ModuleApiCallDependencyInjection extends DependencyInjection instanceof ModuleApiCall {
|
||||
string methodName;
|
||||
|
||||
ModuleApiCallDependencyInjection() {
|
||||
this = call and
|
||||
methodName = call.getMethodName()
|
||||
}
|
||||
ModuleApiCallDependencyInjection() { methodName = super.getMethodName() }
|
||||
|
||||
/**
|
||||
* Gets the argument position for this method call that expects an injectable function.
|
||||
@@ -183,7 +179,7 @@ class ModuleApiCallDependencyInjection extends DependencyInjection {
|
||||
}
|
||||
|
||||
override DataFlow::Node getAnInjectableFunction() {
|
||||
result = call.getArgument(this.injectableArgPos())
|
||||
result = super.getArgument(this.injectableArgPos())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,10 +262,10 @@ abstract class CustomDirective extends DirectiveInstance {
|
||||
DataFlow::SourceNode getMember(string name) { result.flowsTo(this.getMemberInit(name)) }
|
||||
|
||||
/** Gets the method `name` of this directive. */
|
||||
Function getMethod(string name) { DataFlow::valueNode(result) = this.getMember(name) }
|
||||
DataFlow::FunctionNode getMethod(string name) { result = this.getMember(name) }
|
||||
|
||||
/** Gets a link function of this directive. */
|
||||
abstract Function getALinkFunction();
|
||||
abstract DataFlow::FunctionNode getALinkFunction();
|
||||
|
||||
/** Holds if this directive's properties are bound to the controller. */
|
||||
abstract predicate bindsToController();
|
||||
@@ -332,10 +328,10 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
|
||||
|
||||
/** Gets a node that contributes to the return value of the factory function. */
|
||||
override DataFlow::SourceNode getAnInstantiation() {
|
||||
exists(Function factory, InjectableFunction f |
|
||||
exists(DataFlow::FunctionNode factory, InjectableFunction f |
|
||||
f = definition.getAFactoryFunction() and
|
||||
factory = f.asFunction() and
|
||||
result.flowsToExpr(factory.getAReturnedExpr())
|
||||
result.flowsTo(factory.getAReturn())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -344,7 +340,7 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
|
||||
}
|
||||
|
||||
/** Gets the compile function of this directive, if any. */
|
||||
Function getCompileFunction() { result = this.getMethod("compile") }
|
||||
DataFlow::FunctionNode getCompileFunction() { result = this.getMethod("compile") }
|
||||
|
||||
/**
|
||||
* Gets a pre/post link function of this directive defined on its definition object.
|
||||
@@ -365,9 +361,8 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
|
||||
result = this.getMember("link").getAPropertySource(kind)
|
||||
or
|
||||
// { compile: function() { ... return link; } }
|
||||
exists(Expr compileReturn, DataFlow::SourceNode compileReturnSrc |
|
||||
compileReturn = this.getCompileFunction().getAReturnedExpr() and
|
||||
compileReturnSrc.flowsToExpr(compileReturn)
|
||||
exists(DataFlow::SourceNode compileReturnSrc |
|
||||
compileReturnSrc.flowsTo(this.getCompileFunction().getAReturn())
|
||||
|
|
||||
// link = function postLink() { ... }
|
||||
kind = "post" and
|
||||
@@ -380,12 +375,12 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
|
||||
}
|
||||
|
||||
/** Gets the pre-link function of this directive. */
|
||||
Function getPreLinkFunction() { result = this.getLinkFunction("pre").getAstNode() }
|
||||
DataFlow::FunctionNode getPreLinkFunction() { result = this.getLinkFunction("pre") }
|
||||
|
||||
/** Gets the post-link function of this directive. */
|
||||
Function getPostLinkFunction() { result = this.getLinkFunction("post").getAstNode() }
|
||||
DataFlow::FunctionNode getPostLinkFunction() { result = this.getLinkFunction("post") }
|
||||
|
||||
override Function getALinkFunction() { result = this.getLinkFunction(_).getAstNode() }
|
||||
override DataFlow::FunctionNode getALinkFunction() { result = this.getLinkFunction(_) }
|
||||
|
||||
override predicate bindsToController() {
|
||||
this.getMemberInit("bindToController").asExpr().mayHaveBooleanValue(true)
|
||||
@@ -412,7 +407,7 @@ class ComponentDirective extends CustomDirective, MkCustomComponent {
|
||||
comp.getConfig().hasPropertyWrite(name, result)
|
||||
}
|
||||
|
||||
override Function getALinkFunction() { none() }
|
||||
override DataFlow::FunctionNode getALinkFunction() { none() }
|
||||
|
||||
override predicate bindsToController() { none() }
|
||||
|
||||
@@ -561,13 +556,12 @@ class DirectiveTargetName extends string {
|
||||
*
|
||||
* See https://docs.angularjs.org/api/ng/service/$location for details.
|
||||
*/
|
||||
private class LocationFlowSource extends RemoteFlowSource {
|
||||
private class LocationFlowSource extends RemoteFlowSource instanceof DataFlow::MethodCallNode {
|
||||
LocationFlowSource() {
|
||||
exists(ServiceReference service, MethodCallExpr mce, string m, int n |
|
||||
exists(ServiceReference service, string m, int n |
|
||||
service.getName() = "$location" and
|
||||
this.asExpr() = mce and
|
||||
mce = service.getAMethodCall(m) and
|
||||
n = mce.getNumArgument()
|
||||
this = service.getAMethodCall(m) and
|
||||
n = super.getNumArgument()
|
||||
|
|
||||
m = "search" and n < 2
|
||||
or
|
||||
@@ -605,7 +599,7 @@ private class JQLiteObject extends JQuery::ObjectSource::Range {
|
||||
JQLiteObject() {
|
||||
this = angular().getAMemberCall("element")
|
||||
or
|
||||
exists(Parameter param | this = DataFlow::parameterNode(param) |
|
||||
exists(DataFlow::ParameterNode param | this = param |
|
||||
// element parameters to user-functions invoked by AngularJS
|
||||
param = any(LinkFunction link).getElementParameter()
|
||||
or
|
||||
@@ -613,13 +607,13 @@ private class JQLiteObject extends JQuery::ObjectSource::Range {
|
||||
param = d.getCompileFunction().getParameter(0)
|
||||
or
|
||||
exists(DataFlow::FunctionNode f, int i |
|
||||
f.flowsToExpr(d.getCompileFunction().getAReturnedExpr()) and i = 1
|
||||
f.flowsTo(d.getCompileFunction().getAReturn()) and i = 1
|
||||
or
|
||||
f = d.getMember("template") and i = 0
|
||||
or
|
||||
f = d.getMember("templateUrl") and i = 0
|
||||
|
|
||||
param = f.getAstNode().(Function).getParameter(i)
|
||||
param = f.getParameter(i)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -631,99 +625,111 @@ private class JQLiteObject extends JQuery::ObjectSource::Range {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `AngularJSCallNode` instead.
|
||||
* A call to an AngularJS function.
|
||||
*
|
||||
* Used for exposing behavior that is similar to the behavior of other libraries.
|
||||
*/
|
||||
abstract class AngularJSCall extends CallExpr {
|
||||
deprecated class AngularJSCall extends CallExpr {
|
||||
AngularJSCallNode node;
|
||||
|
||||
AngularJSCall() { this.flow() = node }
|
||||
|
||||
/** Holds if `e` is an argument that this call interprets as HTML. */
|
||||
deprecated predicate interpretsArgumentAsHtml(Expr e) { node.interpretsArgumentAsHtml(e.flow()) }
|
||||
|
||||
/** Holds if `e` is an argument that this call stores globally, e.g. in a cookie. */
|
||||
deprecated predicate storesArgumentGlobally(Expr e) { node.storesArgumentGlobally(e.flow()) }
|
||||
|
||||
/** Holds if `e` is an argument that this call interprets as code. */
|
||||
deprecated predicate interpretsArgumentAsCode(Expr e) { node.interpretsArgumentAsCode(e.flow()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to an AngularJS function.
|
||||
*
|
||||
* Used for exposing behavior that is similar to the behavior of other libraries.
|
||||
*/
|
||||
abstract class AngularJSCallNode extends DataFlow::CallNode {
|
||||
/**
|
||||
* Holds if `e` is an argument that this call interprets as HTML.
|
||||
*/
|
||||
abstract predicate interpretsArgumentAsHtml(Expr e);
|
||||
abstract predicate interpretsArgumentAsHtml(DataFlow::Node e);
|
||||
|
||||
/**
|
||||
* Holds if `e` is an argument that this call stores globally, e.g. in a cookie.
|
||||
*/
|
||||
abstract predicate storesArgumentGlobally(Expr e);
|
||||
abstract predicate storesArgumentGlobally(DataFlow::Node e);
|
||||
|
||||
/**
|
||||
* Holds if `e` is an argument that this call interprets as code.
|
||||
*/
|
||||
abstract predicate interpretsArgumentAsCode(Expr e);
|
||||
abstract predicate interpretsArgumentAsCode(DataFlow::Node e);
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a method on the AngularJS object itself.
|
||||
*/
|
||||
private class AngularMethodCall extends AngularJSCall {
|
||||
MethodCallExpr mce;
|
||||
private class AngularMethodCall extends AngularJSCallNode {
|
||||
AngularMethodCall() { this = angular().getAMemberCall(_) }
|
||||
|
||||
AngularMethodCall() {
|
||||
mce = angular().getAMemberCall(_).asExpr() and
|
||||
mce = this
|
||||
override predicate interpretsArgumentAsHtml(DataFlow::Node e) {
|
||||
super.getCalleeName() = "element" and
|
||||
e = super.getArgument(0)
|
||||
}
|
||||
|
||||
override predicate interpretsArgumentAsHtml(Expr e) {
|
||||
mce.getMethodName() = "element" and
|
||||
e = mce.getArgument(0)
|
||||
}
|
||||
override predicate storesArgumentGlobally(DataFlow::Node e) { none() }
|
||||
|
||||
override predicate storesArgumentGlobally(Expr e) { none() }
|
||||
|
||||
override predicate interpretsArgumentAsCode(Expr e) { none() }
|
||||
override predicate interpretsArgumentAsCode(DataFlow::Node e) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a builtin service or one of its methods.
|
||||
*/
|
||||
private class BuiltinServiceCall extends AngularJSCall {
|
||||
CallExpr call;
|
||||
|
||||
private class BuiltinServiceCall extends AngularJSCallNode {
|
||||
BuiltinServiceCall() {
|
||||
exists(BuiltinServiceReference service |
|
||||
service.getAMethodCall(_) = this or
|
||||
service.getACall() = this
|
||||
|
|
||||
call = this
|
||||
)
|
||||
}
|
||||
|
||||
override predicate interpretsArgumentAsHtml(Expr e) {
|
||||
override predicate interpretsArgumentAsHtml(DataFlow::Node e) {
|
||||
exists(ServiceReference service, string methodName |
|
||||
service.getName() = "$sce" and
|
||||
call = service.getAMethodCall(methodName)
|
||||
this = service.getAMethodCall(methodName)
|
||||
|
|
||||
// specialized call
|
||||
(methodName = "trustAsHtml" or methodName = "trustAsCss") and
|
||||
e = call.getArgument(0)
|
||||
e = this.getArgument(0)
|
||||
or
|
||||
// generic call with enum argument
|
||||
methodName = "trustAs" and
|
||||
exists(DataFlow::PropRead prn |
|
||||
prn.asExpr() = call.getArgument(0) and
|
||||
prn = this.getArgument(0) and
|
||||
(prn = service.getAPropertyAccess("HTML") or prn = service.getAPropertyAccess("CSS")) and
|
||||
e = call.getArgument(1)
|
||||
e = this.getArgument(1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate storesArgumentGlobally(Expr e) {
|
||||
override predicate storesArgumentGlobally(DataFlow::Node e) {
|
||||
exists(ServiceReference service, string serviceName, string methodName |
|
||||
service.getName() = serviceName and
|
||||
call = service.getAMethodCall(methodName)
|
||||
this = service.getAMethodCall(methodName)
|
||||
|
|
||||
// AngularJS caches (only available during runtime, so similar to sessionStorage)
|
||||
(serviceName = "$cacheFactory" or serviceName = "$templateCache") and
|
||||
methodName = "put" and
|
||||
e = call.getArgument(1)
|
||||
e = this.getArgument(1)
|
||||
or
|
||||
serviceName = "$cookies" and
|
||||
(methodName = "put" or methodName = "putObject") and
|
||||
e = call.getArgument(1)
|
||||
e = this.getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate interpretsArgumentAsCode(Expr e) {
|
||||
override predicate interpretsArgumentAsCode(DataFlow::Node e) {
|
||||
exists(ScopeServiceReference scope, string methodName |
|
||||
methodName =
|
||||
[
|
||||
@@ -731,22 +737,21 @@ private class BuiltinServiceCall extends AngularJSCall {
|
||||
"$watchGroup"
|
||||
]
|
||||
|
|
||||
call = scope.getAMethodCall(methodName) and
|
||||
e = call.getArgument(0)
|
||||
this = scope.getAMethodCall(methodName) and
|
||||
e = this.getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(ServiceReference service | service.getName() = ["$compile", "$parse", "$interpolate"] |
|
||||
call = service.getACall() and
|
||||
e = call.getArgument(0)
|
||||
this = service.getACall() and
|
||||
e = this.getArgument(0)
|
||||
)
|
||||
or
|
||||
exists(ServiceReference service, CallExpr filterInvocation |
|
||||
exists(ServiceReference service |
|
||||
// `$filter('orderBy')(collection, expression)`
|
||||
service.getName() = "$filter" and
|
||||
call = service.getACall() and
|
||||
call.getArgument(0).mayHaveStringValue("orderBy") and
|
||||
filterInvocation.getCallee() = call and
|
||||
e = filterInvocation.getArgument(1)
|
||||
this = service.getACall() and
|
||||
this.getArgument(0).mayHaveStringValue("orderBy") and
|
||||
e = this.getACall().getArgument(1)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -754,33 +759,33 @@ private class BuiltinServiceCall extends AngularJSCall {
|
||||
/**
|
||||
* A link-function used in a custom AngularJS directive.
|
||||
*/
|
||||
class LinkFunction extends Function {
|
||||
class LinkFunction extends DataFlow::FunctionNode {
|
||||
LinkFunction() { this = any(GeneralDirective d).getALinkFunction() }
|
||||
|
||||
/**
|
||||
* Gets the scope parameter of this function.
|
||||
*/
|
||||
Parameter getScopeParameter() { result = this.getParameter(0) }
|
||||
DataFlow::ParameterNode getScopeParameter() { result = this.getParameter(0) }
|
||||
|
||||
/**
|
||||
* Gets the element parameter of this function (contains a jqLite-wrapped DOM element).
|
||||
*/
|
||||
Parameter getElementParameter() { result = this.getParameter(1) }
|
||||
DataFlow::ParameterNode getElementParameter() { result = this.getParameter(1) }
|
||||
|
||||
/**
|
||||
* Gets the attributes parameter of this function.
|
||||
*/
|
||||
Parameter getAttributesParameter() { result = this.getParameter(2) }
|
||||
DataFlow::ParameterNode getAttributesParameter() { result = this.getParameter(2) }
|
||||
|
||||
/**
|
||||
* Gets the controller parameter of this function.
|
||||
*/
|
||||
Parameter getControllerParameter() { result = this.getParameter(3) }
|
||||
DataFlow::ParameterNode getControllerParameter() { result = this.getParameter(3) }
|
||||
|
||||
/**
|
||||
* Gets the transclude-function parameter of this function.
|
||||
*/
|
||||
Parameter getTranscludeFnParameter() { result = this.getParameter(4) }
|
||||
DataFlow::ParameterNode getTranscludeFnParameter() { result = this.getParameter(4) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -807,29 +812,29 @@ class AngularScope extends TAngularScope {
|
||||
/**
|
||||
* Gets an access to this scope object.
|
||||
*/
|
||||
Expr getAnAccess() {
|
||||
DataFlow::Node getAnAccess() {
|
||||
exists(CustomDirective d | this = d.getAScope() |
|
||||
exists(Parameter p |
|
||||
exists(DataFlow::ParameterNode p |
|
||||
p = d.getController().getDependencyParameter("$scope") or
|
||||
p = d.getALinkFunction().getParameter(0)
|
||||
|
|
||||
result.mayReferToParameter(p)
|
||||
p.flowsTo(result)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::ThisNode dis |
|
||||
dis.flowsToExpr(result) and
|
||||
dis.getBinder().getAstNode() = d.getController().asFunction() and
|
||||
dis.flowsTo(result) and
|
||||
dis.getBinder() = d.getController().asFunction() and
|
||||
d.bindsToController()
|
||||
)
|
||||
or
|
||||
d.hasIsolateScope() and result = d.getMember("scope").asExpr()
|
||||
d.hasIsolateScope() and result = d.getMember("scope")
|
||||
)
|
||||
or
|
||||
exists(DirectiveController c, DOM::ElementDefinition elem, Parameter p |
|
||||
exists(DirectiveController c, DOM::ElementDefinition elem, DataFlow::ParameterNode p |
|
||||
c.boundTo(elem) and
|
||||
this.mayApplyTo(elem) and
|
||||
p = c.getFactoryFunction().getDependencyParameter("$scope") and
|
||||
result.mayReferToParameter(p)
|
||||
p.flowsTo(result)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1022,15 +1027,12 @@ private class RouteInstantiatedController extends Controller {
|
||||
/**
|
||||
* Dataflow for the arguments of AngularJS dependency-injected functions.
|
||||
*/
|
||||
private class DependencyInjectedArgumentInitializer extends DataFlow::AnalyzedNode {
|
||||
private class DependencyInjectedArgumentInitializer extends DataFlow::AnalyzedNode instanceof DataFlow::ParameterNode {
|
||||
DataFlow::AnalyzedNode service;
|
||||
|
||||
DependencyInjectedArgumentInitializer() {
|
||||
exists(
|
||||
AngularJS::InjectableFunction f, Parameter param, AngularJS::CustomServiceDefinition def
|
||||
|
|
||||
this = DataFlow::parameterNode(param) and
|
||||
def.getServiceReference() = f.getAResolvedDependency(param) and
|
||||
exists(AngularJS::InjectableFunction f, AngularJS::CustomServiceDefinition def |
|
||||
def.getServiceReference() = f.getAResolvedDependency(this) and
|
||||
service = def.getAService()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,33 +41,35 @@ abstract class DependencyInjection extends DataFlow::ValueNode {
|
||||
*/
|
||||
abstract class InjectableFunction extends DataFlow::ValueNode {
|
||||
/** Gets the parameter corresponding to dependency `name`. */
|
||||
abstract Parameter getDependencyParameter(string name);
|
||||
abstract DataFlow::ParameterNode getDependencyParameter(string name);
|
||||
|
||||
/**
|
||||
* Gets the `i`th dependency declaration, which is also named `name`.
|
||||
*/
|
||||
abstract AstNode getDependencyDeclaration(int i, string name);
|
||||
abstract DataFlow::Node getDependencyDeclaration(int i, string name);
|
||||
|
||||
/**
|
||||
* Gets an ASTNode for the `name` dependency declaration.
|
||||
* Gets a node for the `name` dependency declaration.
|
||||
*/
|
||||
AstNode getADependencyDeclaration(string name) { result = getDependencyDeclaration(_, name) }
|
||||
DataFlow::Node getADependencyDeclaration(string name) {
|
||||
result = getDependencyDeclaration(_, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ASTNode for the `i`th dependency declaration.
|
||||
* Gets the dataflow node for the `i`th dependency declaration.
|
||||
*/
|
||||
AstNode getDependencyDeclaration(int i) { result = getDependencyDeclaration(i, _) }
|
||||
DataFlow::Node getDependencyDeclaration(int i) { result = getDependencyDeclaration(i, _) }
|
||||
|
||||
/** Gets the function underlying this injectable function. */
|
||||
abstract Function asFunction();
|
||||
abstract DataFlow::FunctionNode asFunction();
|
||||
|
||||
/** Gets a location where this function is explicitly dependency injected. */
|
||||
abstract AstNode getAnExplicitDependencyInjection();
|
||||
/** Gets a node where this function is explicitly dependency injected. */
|
||||
abstract DataFlow::Node getAnExplicitDependencyInjection();
|
||||
|
||||
/**
|
||||
* Gets a service corresponding to the dependency-injected `parameter`.
|
||||
*/
|
||||
ServiceReference getAResolvedDependency(Parameter parameter) {
|
||||
ServiceReference getAResolvedDependency(DataFlow::ParameterNode parameter) {
|
||||
exists(string name, InjectableFunctionServiceRequest request |
|
||||
this = request.getAnInjectedFunction() and
|
||||
parameter = getDependencyParameter(name) and
|
||||
@@ -79,7 +81,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
||||
* Gets a Custom service corresponding to the dependency-injected `parameter`.
|
||||
* (this is a convenience variant of `getAResolvedDependency`)
|
||||
*/
|
||||
DataFlow::Node getCustomServiceDependency(Parameter parameter) {
|
||||
DataFlow::Node getCustomServiceDependency(DataFlow::ParameterNode parameter) {
|
||||
exists(CustomServiceDefinition custom |
|
||||
custom.getServiceReference() = getAResolvedDependency(parameter) and
|
||||
result = custom.getAService()
|
||||
@@ -91,100 +93,88 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
||||
* An injectable function that does not explicitly list its dependencies,
|
||||
* instead relying on implicit matching by parameter names.
|
||||
*/
|
||||
private class FunctionWithImplicitDependencyAnnotation extends InjectableFunction {
|
||||
override Function astNode;
|
||||
|
||||
private class FunctionWithImplicitDependencyAnnotation extends InjectableFunction instanceof DataFlow::FunctionNode {
|
||||
FunctionWithImplicitDependencyAnnotation() {
|
||||
this.(DataFlow::FunctionNode).flowsTo(any(DependencyInjection d).getAnInjectableFunction()) and
|
||||
not exists(getAPropertyDependencyInjection(astNode))
|
||||
not exists(getAPropertyDependencyInjection(this))
|
||||
}
|
||||
|
||||
override Parameter getDependencyParameter(string name) {
|
||||
result = astNode.getParameterByName(name)
|
||||
override DataFlow::ParameterNode getDependencyParameter(string name) {
|
||||
result = super.getParameterByName(name)
|
||||
}
|
||||
|
||||
override Parameter getDependencyDeclaration(int i, string name) {
|
||||
override DataFlow::ParameterNode getDependencyDeclaration(int i, string name) {
|
||||
result.getName() = name and
|
||||
result = astNode.getParameter(i)
|
||||
result = super.getParameter(i)
|
||||
}
|
||||
|
||||
override Function asFunction() { result = astNode }
|
||||
override DataFlow::FunctionNode asFunction() { result = this }
|
||||
|
||||
override AstNode getAnExplicitDependencyInjection() { none() }
|
||||
override DataFlow::Node getAnExplicitDependencyInjection() { none() }
|
||||
}
|
||||
|
||||
private DataFlow::PropWrite getAPropertyDependencyInjection(Function function) {
|
||||
exists(DataFlow::FunctionNode ltf |
|
||||
ltf.getAstNode() = function and
|
||||
result = ltf.getAPropertyWrite("$inject")
|
||||
)
|
||||
private DataFlow::PropWrite getAPropertyDependencyInjection(DataFlow::FunctionNode function) {
|
||||
result = function.getAPropertyWrite("$inject")
|
||||
}
|
||||
|
||||
/**
|
||||
* An injectable function with an `$inject` property that lists its
|
||||
* dependencies.
|
||||
*/
|
||||
private class FunctionWithInjectProperty extends InjectableFunction {
|
||||
override Function astNode;
|
||||
private class FunctionWithInjectProperty extends InjectableFunction instanceof DataFlow::FunctionNode {
|
||||
DataFlow::ArrayCreationNode dependencies;
|
||||
|
||||
FunctionWithInjectProperty() {
|
||||
(
|
||||
this.(DataFlow::FunctionNode).flowsTo(any(DependencyInjection d).getAnInjectableFunction()) or
|
||||
exists(FunctionWithExplicitDependencyAnnotation f | f.asFunction() = astNode)
|
||||
exists(FunctionWithExplicitDependencyAnnotation f | f.asFunction() = this)
|
||||
) and
|
||||
exists(DataFlow::PropWrite pwn |
|
||||
pwn = getAPropertyDependencyInjection(astNode) and
|
||||
pwn = getAPropertyDependencyInjection(this) and
|
||||
pwn.getRhs().getALocalSource() = dependencies
|
||||
)
|
||||
}
|
||||
|
||||
override Parameter getDependencyParameter(string name) {
|
||||
exists(int i | exists(getDependencyDeclaration(i, name)) | result = astNode.getParameter(i))
|
||||
override DataFlow::ParameterNode getDependencyParameter(string name) {
|
||||
exists(int i | exists(getDependencyDeclaration(i, name)) | result = super.getParameter(i))
|
||||
}
|
||||
|
||||
override AstNode getDependencyDeclaration(int i, string name) {
|
||||
exists(DataFlow::ValueNode decl |
|
||||
decl = dependencies.getElement(i) and
|
||||
decl.mayHaveStringValue(name) and
|
||||
result = decl.getAstNode()
|
||||
)
|
||||
override DataFlow::Node getDependencyDeclaration(int i, string name) {
|
||||
result = dependencies.getElement(i) and
|
||||
result.mayHaveStringValue(name)
|
||||
}
|
||||
|
||||
override Function asFunction() { result = astNode }
|
||||
override DataFlow::FunctionNode asFunction() { result = this }
|
||||
|
||||
override AstNode getAnExplicitDependencyInjection() {
|
||||
result = getAPropertyDependencyInjection(astNode).getAstNode()
|
||||
override DataFlow::Node getAnExplicitDependencyInjection() {
|
||||
result = getAPropertyDependencyInjection(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An injectable function embedded in an array of dependencies.
|
||||
*/
|
||||
private class FunctionWithExplicitDependencyAnnotation extends InjectableFunction {
|
||||
private class FunctionWithExplicitDependencyAnnotation extends InjectableFunction instanceof DataFlow::ArrayCreationNode {
|
||||
DataFlow::FunctionNode function;
|
||||
override ArrayExpr astNode;
|
||||
|
||||
FunctionWithExplicitDependencyAnnotation() {
|
||||
this.(DataFlow::SourceNode).flowsTo(any(DependencyInjection d).getAnInjectableFunction()) and
|
||||
function.flowsToExpr(astNode.getElement(astNode.getSize() - 1))
|
||||
function.flowsTo(super.getElement(super.getSize() - 1))
|
||||
}
|
||||
|
||||
override Parameter getDependencyParameter(string name) {
|
||||
exists(int i | astNode.getElement(i).mayHaveStringValue(name) |
|
||||
result = asFunction().getParameter(i)
|
||||
)
|
||||
override DataFlow::ParameterNode getDependencyParameter(string name) {
|
||||
exists(int i | super.getElement(i).mayHaveStringValue(name) | result = function.getParameter(i))
|
||||
}
|
||||
|
||||
override AstNode getDependencyDeclaration(int i, string name) {
|
||||
result = astNode.getElement(i) and
|
||||
result.(Expr).mayHaveStringValue(name)
|
||||
override DataFlow::Node getDependencyDeclaration(int i, string name) {
|
||||
result = super.getElement(i) and
|
||||
result.mayHaveStringValue(name)
|
||||
}
|
||||
|
||||
override Function asFunction() { result = function.getAstNode() }
|
||||
override DataFlow::FunctionNode asFunction() { result = function }
|
||||
|
||||
override AstNode getAnExplicitDependencyInjection() {
|
||||
result = astNode or
|
||||
override DataFlow::Node getAnExplicitDependencyInjection() {
|
||||
result = this or
|
||||
result = function.(InjectableFunction).getAnExplicitDependencyInjection()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,25 +38,25 @@ abstract class ServiceReference extends TServiceReference {
|
||||
* Gets a data flow node that may refer to this service.
|
||||
*/
|
||||
DataFlow::SourceNode getAReference() {
|
||||
result = DataFlow::parameterNode(any(ServiceRequest request).getDependencyParameter(this))
|
||||
result = any(ServiceRequestNode request).getDependencyParameter(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an access to the referenced service.
|
||||
*/
|
||||
Expr getAnAccess() {
|
||||
result.mayReferToParameter(any(ServiceRequest request).getDependencyParameter(this))
|
||||
DataFlow::Node getAnAccess() {
|
||||
any(ServiceRequestNode request).getDependencyParameter(this).flowsTo(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a call that invokes the referenced service.
|
||||
*/
|
||||
CallExpr getACall() { result.getCallee() = getAnAccess() }
|
||||
DataFlow::CallNode getACall() { result.getCalleeNode() = getAnAccess() }
|
||||
|
||||
/**
|
||||
* Gets a method call that invokes method `methodName` on the referenced service.
|
||||
*/
|
||||
MethodCallExpr getAMethodCall(string methodName) {
|
||||
DataFlow::MethodCallNode getAMethodCall(string methodName) {
|
||||
result.getReceiver() = getAnAccess() and
|
||||
result.getMethodName() = methodName
|
||||
}
|
||||
@@ -65,7 +65,7 @@ abstract class ServiceReference extends TServiceReference {
|
||||
* Gets an access to property `propertyName` on the referenced service.
|
||||
*/
|
||||
DataFlow::PropRef getAPropertyAccess(string propertyName) {
|
||||
result.getBase().asExpr() = getAnAccess() and
|
||||
result.getBase() = getAnAccess() and
|
||||
result.getPropertyName() = propertyName
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class BuiltinServiceReference extends ServiceReference, MkBuiltinServiceReferenc
|
||||
DataFlow::ParameterNode builtinServiceRef(string serviceName) {
|
||||
exists(InjectableFunction f, BuiltinServiceReference service |
|
||||
service.getName() = serviceName and
|
||||
result = DataFlow::parameterNode(f.getDependencyParameter(serviceName))
|
||||
result = f.getDependencyParameter(serviceName)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ class FilterDefinition extends CustomSpecialServiceDefinition {
|
||||
override DataFlow::SourceNode getAService() {
|
||||
exists(InjectableFunction f |
|
||||
f = factoryFunction.getALocalSource() and
|
||||
result.flowsToExpr(f.asFunction().getAReturnedExpr())
|
||||
result.flowsTo(f.asFunction().getAReturn())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ class AnimationDefinition extends CustomSpecialServiceDefinition {
|
||||
override DataFlow::SourceNode getAService() {
|
||||
exists(InjectableFunction f |
|
||||
f = factoryFunction.getALocalSource() and
|
||||
result.flowsToExpr(f.asFunction().getAReturnedExpr())
|
||||
result.flowsTo(f.asFunction().getAReturn())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -446,22 +446,37 @@ BuiltinServiceReference getBuiltinServiceOfKind(string kind) {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ServiceRequestNode` instead.
|
||||
* A request for one or more AngularJS services.
|
||||
*/
|
||||
abstract class ServiceRequest extends Expr {
|
||||
deprecated class ServiceRequest extends Expr {
|
||||
ServiceRequestNode node;
|
||||
|
||||
ServiceRequest() { this.flow() = node }
|
||||
|
||||
/** Gets the parameter of this request into which `service` is injected. */
|
||||
deprecated Parameter getDependencyParameter(ServiceReference service) {
|
||||
result.flow() = node.getDependencyParameter(service)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A request for one or more AngularJS services.
|
||||
*/
|
||||
abstract class ServiceRequestNode extends DataFlow::Node {
|
||||
/**
|
||||
* Gets the parameter of this request into which `service` is injected.
|
||||
*/
|
||||
abstract Parameter getDependencyParameter(ServiceReference service);
|
||||
abstract DataFlow::ParameterNode getDependencyParameter(ServiceReference service);
|
||||
}
|
||||
|
||||
/**
|
||||
* The request for a scope service in the form of the link-function of a directive.
|
||||
*/
|
||||
private class LinkFunctionWithScopeInjection extends ServiceRequest {
|
||||
private class LinkFunctionWithScopeInjection extends ServiceRequestNode {
|
||||
LinkFunctionWithScopeInjection() { this instanceof LinkFunction }
|
||||
|
||||
override Parameter getDependencyParameter(ServiceReference service) {
|
||||
override DataFlow::ParameterNode getDependencyParameter(ServiceReference service) {
|
||||
service instanceof ScopeServiceReference and
|
||||
result = this.(LinkFunction).getScopeParameter()
|
||||
}
|
||||
@@ -470,10 +485,10 @@ private class LinkFunctionWithScopeInjection extends ServiceRequest {
|
||||
/**
|
||||
* A request for a service, in the form of a dependency-injected function.
|
||||
*/
|
||||
class InjectableFunctionServiceRequest extends ServiceRequest {
|
||||
class InjectableFunctionServiceRequest extends ServiceRequestNode {
|
||||
InjectableFunction injectedFunction;
|
||||
|
||||
InjectableFunctionServiceRequest() { injectedFunction.getAstNode() = this }
|
||||
InjectableFunctionServiceRequest() { injectedFunction = this }
|
||||
|
||||
/**
|
||||
* Gets the function of this request.
|
||||
@@ -494,16 +509,16 @@ class InjectableFunctionServiceRequest extends ServiceRequest {
|
||||
result.isInjectable()
|
||||
}
|
||||
|
||||
override Parameter getDependencyParameter(ServiceReference service) {
|
||||
override DataFlow::ParameterNode getDependencyParameter(ServiceReference service) {
|
||||
service = injectedFunction.getAResolvedDependency(result)
|
||||
}
|
||||
}
|
||||
|
||||
private DataFlow::SourceNode getFactoryFunctionResult(RecipeDefinition def) {
|
||||
exists(Function factoryFunction, InjectableFunction f |
|
||||
exists(DataFlow::FunctionNode factoryFunction, InjectableFunction f |
|
||||
f = def.getAFactoryFunction() and
|
||||
factoryFunction = f.asFunction() and
|
||||
result.flowsToExpr(factoryFunction.getAReturnedExpr())
|
||||
result.flowsTo(factoryFunction.getAReturn())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -562,7 +577,7 @@ class ServiceRecipeDefinition extends RecipeDefinition {
|
||||
|
||||
exists(InjectableFunction f |
|
||||
f = getAFactoryFunction() and
|
||||
result.getAstNode() = f.asFunction()
|
||||
result = f.asFunction()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -608,7 +623,7 @@ class ProviderRecipeDefinition extends RecipeDefinition {
|
||||
|
||||
exists(DataFlow::ThisNode thiz, InjectableFunction f |
|
||||
f = getAFactoryFunction() and
|
||||
thiz.getBinder().getFunction() = f.asFunction() and
|
||||
thiz.getBinder() = f.asFunction() and
|
||||
result = thiz.getAPropertySource("$get")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -67,8 +67,6 @@ module CleartextStorage {
|
||||
* An expression stored by AngularJS.
|
||||
*/
|
||||
class AngularJSStorageSink extends Sink {
|
||||
AngularJSStorageSink() {
|
||||
any(AngularJS::AngularJSCall call).storesArgumentGlobally(this.asExpr())
|
||||
}
|
||||
AngularJSStorageSink() { any(AngularJS::AngularJSCallNode call).storesArgumentGlobally(this) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ module ClientSideUrlRedirect {
|
||||
// A redirection using the AngularJS `$location` service
|
||||
exists(AngularJS::ServiceReference service |
|
||||
service.getName() = "$location" and
|
||||
this.asExpr() = service.getAMethodCall("url").getArgument(0)
|
||||
this = service.getAMethodCall("url").getArgument(0)
|
||||
) and
|
||||
xss = false
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ module CodeInjection {
|
||||
*/
|
||||
class AngularJSExpressionSink extends Sink, DataFlow::ValueNode {
|
||||
AngularJSExpressionSink() {
|
||||
any(AngularJS::AngularJSCall call).interpretsArgumentAsCode(this.asExpr())
|
||||
any(AngularJS::AngularJSCallNode call).interpretsArgumentAsCode(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ module DomBasedXss {
|
||||
)
|
||||
or
|
||||
// call to an Angular method that interprets its argument as HTML
|
||||
any(AngularJS::AngularJSCall call).interpretsArgumentAsHtml(this.asExpr())
|
||||
any(AngularJS::AngularJSCallNode call).interpretsArgumentAsHtml(this)
|
||||
or
|
||||
// call to a WinJS function that interprets its argument as HTML
|
||||
exists(DataFlow::MethodCallNode mcn, string m |
|
||||
|
||||
@@ -31,8 +31,8 @@ module XmlBomb {
|
||||
/**
|
||||
* An access to `document.location`, considered as a flow source for XML bomb vulnerabilities.
|
||||
*/
|
||||
class LocationAsSource extends Source, DataFlow::ValueNode {
|
||||
LocationAsSource() { isLocation(astNode) }
|
||||
class LocationAsSource extends Source {
|
||||
LocationAsSource() { isLocationNode(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,8 +31,8 @@ module Xxe {
|
||||
/**
|
||||
* An access to `document.location`, considered as a flow source for XXE vulnerabilities.
|
||||
*/
|
||||
class LocationAsSource extends Source, DataFlow::ValueNode {
|
||||
LocationAsSource() { isLocation(astNode) }
|
||||
class LocationAsSource extends Source {
|
||||
LocationAsSource() { isLocationNode(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,17 +42,19 @@ predicate isABuiltinEventName(string name) {
|
||||
* Holds if user code emits or broadcasts an event named `name`.
|
||||
*/
|
||||
predicate isAUserDefinedEventName(string name) {
|
||||
exists(string methodName, MethodCallExpr mce | methodName = "$emit" or methodName = "$broadcast" |
|
||||
mce.getArgument(0).mayHaveStringValue(name) and
|
||||
exists(string methodName, DataFlow::MethodCallNode mcn |
|
||||
methodName = "$emit" or methodName = "$broadcast"
|
||||
|
|
||||
mcn.getArgument(0).mayHaveStringValue(name) and
|
||||
(
|
||||
// dataflow based scope resolution
|
||||
mce = any(AngularJS::ScopeServiceReference scope).getAMethodCall(methodName)
|
||||
mcn = any(AngularJS::ScopeServiceReference scope).getAMethodCall(methodName)
|
||||
or
|
||||
// heuristic scope resolution: assume parameters like `$scope` or `$rootScope` are AngularJS scope objects
|
||||
exists(SimpleParameter param |
|
||||
exists(DataFlow::ParameterNode param |
|
||||
param.getName() = any(AngularJS::ScopeServiceReference scope).getName() and
|
||||
mce.getReceiver().mayReferToParameter(param) and
|
||||
mce.getMethodName() = methodName
|
||||
param.getAMethodCall() = mcn and
|
||||
mcn.getMethodName() = methodName
|
||||
)
|
||||
or
|
||||
// a call in an AngularJS expression
|
||||
@@ -64,7 +66,7 @@ predicate isAUserDefinedEventName(string name) {
|
||||
)
|
||||
}
|
||||
|
||||
from AngularJS::ScopeServiceReference scope, MethodCallExpr mce, string eventName
|
||||
from AngularJS::ScopeServiceReference scope, DataFlow::MethodCallNode mce, string eventName
|
||||
where
|
||||
mce = scope.getAMethodCall("$on") and
|
||||
mce.getArgument(0).mayHaveStringValue(eventName) and
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import javascript
|
||||
|
||||
from AngularJS::InjectableFunction f, SimpleParameter p, string msg
|
||||
from AngularJS::InjectableFunction f, DataFlow::ParameterNode p, string msg
|
||||
where
|
||||
p = f.asFunction().getAParameter() and
|
||||
(
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import javascript
|
||||
|
||||
from MethodCallExpr mce, AngularJS::BuiltinServiceReference service
|
||||
from DataFlow::MethodCallNode mce, AngularJS::BuiltinServiceReference service
|
||||
where
|
||||
service.getName() = "$sceProvider" and
|
||||
mce = service.getAMethodCall("enabled") and
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
import javascript
|
||||
|
||||
from AngularJS::ServiceReference compile, SimpleParameter elem, CallExpr c
|
||||
from AngularJS::ServiceReference compile, DataFlow::ParameterNode elem, DataFlow::CallNode c
|
||||
where
|
||||
compile.getName() = "$compile" and
|
||||
elem =
|
||||
@@ -24,7 +24,7 @@ where
|
||||
.(AngularJS::LinkFunction)
|
||||
.getElementParameter() and
|
||||
c = compile.getACall() and
|
||||
c.getArgument(0).mayReferToParameter(elem) and
|
||||
elem.flowsTo(c.getArgument(0)) and
|
||||
// don't flag $compile calls that specify a `maxPriority`
|
||||
c.getNumArgument() < 3
|
||||
select c, "This call to $compile may cause double compilation of '" + elem + "'."
|
||||
|
||||
@@ -12,16 +12,17 @@
|
||||
import javascript
|
||||
import semmle.javascript.RestrictedLocations
|
||||
|
||||
predicate isRepeatedDependency(AngularJS::InjectableFunction f, string name, AstNode location) {
|
||||
predicate isRepeatedDependency(AngularJS::InjectableFunction f, string name, DataFlow::Node node) {
|
||||
exists(int i, int j |
|
||||
i < j and
|
||||
exists(f.getDependencyDeclaration(i, name)) and
|
||||
location = f.getDependencyDeclaration(j, name)
|
||||
node = f.getDependencyDeclaration(j, name)
|
||||
)
|
||||
}
|
||||
|
||||
from AngularJS::InjectableFunction f, AstNode node, string name
|
||||
from AngularJS::InjectableFunction f, DataFlow::Node node, string name
|
||||
where
|
||||
isRepeatedDependency(f, name, node) and
|
||||
not count(f.asFunction().getParameterByName(name)) > 1 // avoid duplicating reports from js/duplicate-parameter-name
|
||||
select f.asFunction().(FirstLineOf), "This function has a duplicate dependency '$@'.", node, name
|
||||
select f.asFunction().getFunction().(FirstLineOf), "This function has a duplicate dependency '$@'.",
|
||||
node, name
|
||||
|
||||
@@ -23,7 +23,7 @@ predicate isResourceUrlWhitelist(
|
||||
) {
|
||||
exists(AngularJS::ServiceReference service |
|
||||
service.getName() = "$sceDelegateProvider" and
|
||||
setupCall.asExpr() = service.getAMethodCall("resourceUrlWhitelist") and
|
||||
setupCall = service.getAMethodCall("resourceUrlWhitelist") and
|
||||
list.flowsTo(setupCall.getArgument(0))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
import javascript
|
||||
import semmle.javascript.RestrictedLocations
|
||||
|
||||
from AngularJS::InjectableFunction f, AstNode explicitInjection
|
||||
from AngularJS::InjectableFunction f, DataFlow::Node explicitInjection
|
||||
where
|
||||
count(f.getAnExplicitDependencyInjection()) > 1 and
|
||||
explicitInjection = f.getAnExplicitDependencyInjection()
|
||||
select f.asFunction().(FirstLineOf), "This function has $@ defined in multiple places.",
|
||||
explicitInjection, "dependency injections"
|
||||
select f.asFunction().getFunction().(FirstLineOf),
|
||||
"This function has $@ defined in multiple places.", explicitInjection, "dependency injections"
|
||||
|
||||
@@ -13,9 +13,9 @@ import javascript
|
||||
import Declarations.UnusedParameter
|
||||
import semmle.javascript.RestrictedLocations
|
||||
|
||||
predicate isUnusedParameter(Function f, string msg, Parameter parameter) {
|
||||
predicate isUnusedParameter(DataFlow::FunctionNode f, string msg, Parameter parameter) {
|
||||
exists(Variable pv |
|
||||
isUnused(f, parameter, pv, _) and
|
||||
isUnused(f.getFunction(), parameter, pv, _) and
|
||||
not isAnAccidentallyUnusedParameter(parameter) and // avoid double alerts
|
||||
msg = "Unused dependency " + pv.getName() + "."
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import javascript
|
||||
|
||||
from AngularJS::ScopeServiceReference s, MethodCallExpr mce
|
||||
from AngularJS::ScopeServiceReference s, DataFlow::MethodCallNode mce
|
||||
where mce = s.getAMethodCall(_)
|
||||
select mce
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import javascript
|
||||
private import AngularJS
|
||||
|
||||
from InjectableFunction f, SimpleParameter p, DataFlow::Node nd
|
||||
from InjectableFunction f, DataFlow::ParameterNode p, DataFlow::Node nd
|
||||
where nd = f.getCustomServiceDependency(p)
|
||||
select p.getName(), nd
|
||||
|
||||
@@ -1,92 +1,137 @@
|
||||
| isolate scope for directive1 | scope-access.js:4:41:4:45 | scope |
|
||||
| isolate scope for directive1 | scope-access.js:4:41:4:45 | scope |
|
||||
| isolate scope for directive1 | scope-access.js:5:17:5:21 | scope |
|
||||
| isolate scope for directive1 | scope-access.js:7:20:7:21 | {} |
|
||||
| isolate scope for directive2 | scope-access.js:12:34:12:39 | $scope |
|
||||
| isolate scope for directive2 | scope-access.js:12:34:12:39 | $scope |
|
||||
| isolate scope for directive2 | scope-access.js:13:17:13:22 | $scope |
|
||||
| isolate scope for directive2 | scope-access.js:15:20:15:21 | {} |
|
||||
| isolate scope for directive3 | scope-access.js:20:39:20:44 | $scope |
|
||||
| isolate scope for directive3 | scope-access.js:20:39:20:44 | $scope |
|
||||
| isolate scope for directive3 | scope-access.js:21:17:21:22 | $scope |
|
||||
| isolate scope for directive3 | scope-access.js:23:20:23:21 | {} |
|
||||
| isolate scope for directive4 | scope-access.js:28:45:28:45 | a |
|
||||
| isolate scope for directive4 | scope-access.js:28:45:28:45 | a |
|
||||
| isolate scope for directive4 | scope-access.js:29:17:29:17 | a |
|
||||
| isolate scope for directive4 | scope-access.js:31:20:31:21 | {} |
|
||||
| isolate scope for directive5 | scope-access.js:36:25:36:24 | this |
|
||||
| isolate scope for directive5 | scope-access.js:37:17:37:20 | this |
|
||||
| isolate scope for directive5 | scope-access.js:39:20:39:21 | {} |
|
||||
| isolate scope for directive6 | scope-access.js:45:25:45:24 | this |
|
||||
| isolate scope for directive6 | scope-access.js:46:18:46:26 | return of anonymous function |
|
||||
| isolate scope for directive6 | scope-access.js:46:23:46:26 | this |
|
||||
| isolate scope for directive6 | scope-access.js:48:20:48:21 | {} |
|
||||
| isolate scope for myCustomer | dev-guide-5.js:11:12:13:5 | { // Sc ... y\\n } |
|
||||
| isolate scope for myCustomer | dev-guide-6.js:11:12:13:5 | { // Sc ... y\\n } |
|
||||
| scope for <directive7>...</> | scope-access.js:54:34:54:39 | $scope |
|
||||
| scope for <directive7>...</> | scope-access.js:54:34:54:39 | $scope |
|
||||
| scope for <directive7>...</> | scope-access.js:55:17:55:22 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:4:49:4:54 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:4:49:4:54 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:4:49:4:54 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:7:3:7:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:7:21:7:20 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:8:5:8:10 | $scope |
|
||||
| scope for <div>...</> | dev-guide-1.js:8:34:8:39 | $scope |
|
||||
| scope for <div>...</> | dev-guide-2.js:4:66:4:71 | $scope |
|
||||
| scope for <div>...</> | dev-guide-2.js:4:66:4:71 | $scope |
|
||||
| scope for <div>...</> | dev-guide-2.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-2.js:8:51:8:56 | $scope |
|
||||
| scope for <div>...</> | dev-guide-2.js:8:51:8:56 | $scope |
|
||||
| scope for <div>...</> | dev-guide-2.js:9:3:9:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <div>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <div>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <div>...</> | dev-guide-3.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-3.js:6:3:6:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-3.js:6:25:6:24 | $scope |
|
||||
| scope for <div>...</> | dev-guide-3.js:7:5:7:10 | $scope |
|
||||
| scope for <div>...</> | dev-guide-4.js:4:52:4:57 | $scope |
|
||||
| scope for <div>...</> | dev-guide-4.js:4:52:4:57 | $scope |
|
||||
| scope for <div>...</> | dev-guide-4.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-4.js:10:51:10:56 | $scope |
|
||||
| scope for <div>...</> | dev-guide-4.js:10:51:10:56 | $scope |
|
||||
| scope for <div>...</> | dev-guide-4.js:11:3:11:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:6:3:6:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-5.js:6:3:6:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:5:3:5:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:6:3:6:8 | $scope |
|
||||
| scope for <div>...</> | dev-guide-6.js:6:3:6:8 | $scope |
|
||||
| scope for <elementthatusescontroller1>...</> | scope-access.js:59:52:59:57 | $scope |
|
||||
| scope for <elementthatusescontroller1>...</> | scope-access.js:59:52:59:57 | $scope |
|
||||
| scope for <elementthatusescontroller1>...</> | scope-access.js:60:9:60:14 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:5:3:5:8 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:5:3:5:8 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:6:3:6:8 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:6:3:6:8 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:6:25:6:24 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:6:25:6:24 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:7:5:7:10 | $scope |
|
||||
| scope for <li>...</> | dev-guide-3.js:7:5:7:10 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:4:49:4:54 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:4:49:4:54 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:4:49:4:54 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:7:3:7:8 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:7:21:7:20 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:8:5:8:10 | $scope |
|
||||
| scope in dev-guide-1.html | dev-guide-1.js:8:34:8:39 | $scope |
|
||||
| scope in dev-guide-2.html | dev-guide-2.js:4:66:4:71 | $scope |
|
||||
| scope in dev-guide-2.html | dev-guide-2.js:4:66:4:71 | $scope |
|
||||
| scope in dev-guide-2.html | dev-guide-2.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-2.html | dev-guide-2.js:8:51:8:56 | $scope |
|
||||
| scope in dev-guide-2.html | dev-guide-2.js:8:51:8:56 | $scope |
|
||||
| scope in dev-guide-2.html | dev-guide-2.js:9:3:9:8 | $scope |
|
||||
| scope in dev-guide-3.html | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope in dev-guide-3.html | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope in dev-guide-3.html | dev-guide-3.js:4:52:4:57 | $scope |
|
||||
| scope in dev-guide-3.html | dev-guide-3.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-3.html | dev-guide-3.js:6:3:6:8 | $scope |
|
||||
| scope in dev-guide-3.html | dev-guide-3.js:6:25:6:24 | $scope |
|
||||
| scope in dev-guide-3.html | dev-guide-3.js:7:5:7:10 | $scope |
|
||||
| scope in dev-guide-4.html | dev-guide-4.js:4:52:4:57 | $scope |
|
||||
| scope in dev-guide-4.html | dev-guide-4.js:4:52:4:57 | $scope |
|
||||
| scope in dev-guide-4.html | dev-guide-4.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-4.html | dev-guide-4.js:10:51:10:56 | $scope |
|
||||
| scope in dev-guide-4.html | dev-guide-4.js:10:51:10:56 | $scope |
|
||||
| scope in dev-guide-4.html | dev-guide-4.js:11:3:11:8 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-5.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-5.js:6:3:6:8 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-6.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-5.html | dev-guide-6.js:6:3:6:8 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-5.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-5.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-5.js:6:3:6:8 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-6.js:4:47:4:52 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-6.js:5:3:5:8 | $scope |
|
||||
| scope in dev-guide-6.html | dev-guide-6.js:6:3:6:8 | $scope |
|
||||
| scope in scope-access.html | scope-access.js:54:34:54:39 | $scope |
|
||||
| scope in scope-access.html | scope-access.js:54:34:54:39 | $scope |
|
||||
| scope in scope-access.html | scope-access.js:55:17:55:22 | $scope |
|
||||
| scope in scope-access.html | scope-access.js:59:52:59:57 | $scope |
|
||||
| scope in scope-access.html | scope-access.js:59:52:59:57 | $scope |
|
||||
| scope in scope-access.html | scope-access.js:60:9:60:14 | $scope |
|
||||
|
||||
Reference in New Issue
Block a user