mirror of
https://github.com/github/codeql.git
synced 2026-04-28 10:15:14 +02:00
JS: Track flow into ES accessors
This commit is contained in:
@@ -531,6 +531,13 @@ module DataFlow {
|
||||
predicate isPrivateField() {
|
||||
getPropertyName().charAt(0) = "#" and getPropertyNameExpr() instanceof Label
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an accessor (`get` or `set` method) that may be invoked by this property reference.
|
||||
*/
|
||||
final DataFlow::FunctionNode getAnAccessorCallee() {
|
||||
result = CallGraph::getAnAccessorCallee(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -162,4 +162,18 @@ module CallGraph {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a getter or setter invoked as a result of the given property access.
|
||||
*/
|
||||
cached
|
||||
DataFlow::FunctionNode getAnAccessorCallee(DataFlow::PropRef ref) {
|
||||
exists(DataFlow::ClassNode cls, string name |
|
||||
ref = cls.getAnInstanceReference().getAPropertyRead(name) and
|
||||
result = cls.getInstanceMember(name, DataFlow::MemberKind::getter())
|
||||
or
|
||||
ref = cls.getAnInstanceReference().getAPropertyWrite(name) and
|
||||
result = cls.getInstanceMember(name, DataFlow::MemberKind::setter())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ predicate shouldTrackProperties(AbstractValue obj) {
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate returnExpr(Function f, DataFlow::Node source, DataFlow::Node sink) {
|
||||
sink.asExpr() = f.getAReturnedExpr() and source = sink
|
||||
sink.asExpr() = f.getAReturnedExpr() and source = sink and
|
||||
not f = any(SetterMethodDeclaration decl).getBody()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +121,11 @@ private module CachedSteps {
|
||||
* Holds if `invk` may invoke `f`.
|
||||
*/
|
||||
cached
|
||||
predicate calls(DataFlow::InvokeNode invk, Function f) { f = invk.getACallee(0) }
|
||||
predicate calls(DataFlow::SourceNode invk, Function f) {
|
||||
f = invk.(DataFlow::InvokeNode).getACallee(0)
|
||||
or
|
||||
f = invk.(DataFlow::PropRef).getAnAccessorCallee().getFunction()
|
||||
}
|
||||
|
||||
private predicate callsBoundInternal(
|
||||
DataFlow::InvokeNode invk, Function f, int boundArgs, boolean contextDependent
|
||||
@@ -177,11 +182,11 @@ private module CachedSteps {
|
||||
*/
|
||||
cached
|
||||
predicate argumentPassing(
|
||||
DataFlow::InvokeNode invk, DataFlow::ValueNode arg, Function f, DataFlow::SourceNode parm
|
||||
DataFlow::SourceNode invk, DataFlow::ValueNode arg, Function f, DataFlow::SourceNode parm
|
||||
) {
|
||||
calls(invk, f) and
|
||||
(
|
||||
exists(int i | arg = invk.getArgument(i) |
|
||||
exists(int i | arg = invk.(DataFlow::InvokeNode).getArgument(i) |
|
||||
exists(Parameter p |
|
||||
f.getParameter(i) = p and
|
||||
not p.isRestParameter() and
|
||||
@@ -193,6 +198,12 @@ private module CachedSteps {
|
||||
or
|
||||
arg = invk.(DataFlow::CallNode).getReceiver() and
|
||||
parm = DataFlow::thisNode(f)
|
||||
or
|
||||
arg = invk.(DataFlow::PropRef).getBase() and
|
||||
parm = DataFlow::thisNode(f)
|
||||
or
|
||||
arg = invk.(DataFlow::PropWrite).getRhs() and
|
||||
parm = DataFlow::parameterNode(f.getParameter(0))
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node callback, int i, Parameter p |
|
||||
@@ -213,7 +224,7 @@ private module CachedSteps {
|
||||
callsBound(invk, f, boundArgs) and
|
||||
f.getParameter(boundArgs + i) = p and
|
||||
not p.isRestParameter() and
|
||||
arg = invk.getArgument(i) and
|
||||
arg = invk.(DataFlow::InvokeNode).getArgument(i) and
|
||||
parm = DataFlow::parameterNode(p)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user