JavaScript: Fix IllegalInvocation.

This fixes false positives that arise when a call such as `f.apply` can either be interpreted as a reflective invocation of `f`, or a normal call to method `apply` of `f`.
This commit is contained in:
Max Schaefer
2019-09-22 16:04:05 +01:00
parent 478095223e
commit 149ae5d7ab
5 changed files with 21 additions and 1 deletions

View File

@@ -58,7 +58,8 @@ where
// filter out some easy cases
not isCallToFunction(cs) and
// conservatively only flag call sites where _all_ callees are illegal
forex(Function otherCallee | otherCallee = cs.getACallee() |
forex(DataFlow::InvokeNode cs2, Function otherCallee |
cs2.getInvokeExpr() = cs.getInvokeExpr() and otherCallee = cs2.getACallee() |
illegalInvocation(cs, otherCallee, _, _)
)
select cs, "Illegal invocation of $@ " + how + ".", callee, calleeDesc

View File

@@ -935,6 +935,9 @@ module DataFlow {
* and either with or without `new`.
*/
abstract class InvokeNodeDef extends DataFlow::Node {
/** Gets the syntactic invoke expression underlying this function invocation. */
abstract InvokeExpr getInvokeExpr();
/** Gets the name of the function or method being invoked, if it can be determined. */
abstract string getCalleeName();
@@ -985,6 +988,8 @@ module DataFlow {
class ExplicitInvokeNode extends InvokeNodeDef, DataFlow::ValueNode {
override InvokeExpr astNode;
override InvokeExpr getInvokeExpr() { result = astNode }
override string getCalleeName() { result = astNode.getCalleeName() }
override DataFlow::Node getCalleeNode() { result = DataFlow::valueNode(astNode.getCallee()) }
@@ -1046,6 +1051,8 @@ module DataFlow {
ReflectiveCallNodeDef() { this = TReflectiveCallNode(originalCall.asExpr(), kind) }
override InvokeExpr getInvokeExpr() { result = originalCall.getInvokeExpr() }
override string getCalleeName() {
result = originalCall.getReceiver().asExpr().(PropAccess).getPropertyName()
}

View File

@@ -34,6 +34,9 @@ class InvokeNode extends DataFlow::SourceNode {
InvokeNode() { this = impl }
/** Gets the syntactic invoke expression underlying this function invocation. */
InvokeExpr getInvokeExpr() { result = impl.getInvokeExpr() }
/** Gets the name of the function or method being invoked, if it can be determined. */
string getCalleeName() { result = impl.getCalleeName() }

View File

@@ -45,4 +45,12 @@ new h() // NOT OK
C.call(); // NOT OK
C.apply(); // NOT OK
class E {
static call() {}
static apply() {}
}
E.call(); // OK
E.apply(); // OK
//semmle-extractor-options: --experimental