JS: Simplify call graph metric

This commit is contained in:
Asger F
2019-09-10 11:21:31 +01:00
parent c8e5be74d5
commit c5f29e0a1d

View File

@@ -47,97 +47,6 @@ class RelevantFunction extends Function {
}
}
/**
* Holds if `name` is a the name of an external module.
*/
predicate isExternalLibrary(string name) {
// Mentioned in package.json
any(Dependency dep).info(name, _) or
// Node.js built-in
name = "assert" or
name = "async_hooks" or
name = "child_process" or
name = "cluster" or
name = "crypto" or
name = "dns" or
name = "domain" or
name = "events" or
name = "fs" or
name = "http" or
name = "http2" or
name = "https" or
name = "inspector" or
name = "net" or
name = "os" or
name = "path" or
name = "perf_hooks" or
name = "process" or
name = "punycode" or
name = "querystring" or
name = "readline" or
name = "repl" or
name = "stream" or
name = "string_decoder" or
name = "timer" or
name = "tls" or
name = "trace_events" or
name = "tty" or
name = "dgram" or
name = "url" or
name = "util" or
name = "v8" or
name = "vm" or
name = "worker_threads" or
name = "zlib"
}
/**
* Holds if the global variable `name` is defined externally.
*/
predicate isExternalGlobal(string name) {
exists(ExternalGlobalDecl decl | decl.getName() = name)
or
exists(Dependency dep |
// If name is never assigned anywhere, and it coincides with a dependency,
// it's most likely coming from there.
dep.info(name, _) and
not exists(Assignment assign | assign.getLhs().(GlobalVarAccess).getName() = name)
)
or
name = "_"
}
/**
* Gets a node that was derived from an import of `moduleName`.
*
* This is a rough approximation as it follows all property reads, invocations,
* and callbacks, so some of these might refer to internal objects.
*
* Additionally, we don't recognize when a project imports another file in the
* same project using its module name (for example import "vscode" from inside the vscode project).
*/
SourceNode externalNode() {
exists(string moduleName |
result = moduleImport(moduleName) and
isExternalLibrary(moduleName)
)
or
exists(string name |
result = globalVarRef(name) and
isExternalGlobal(name)
)
or
result = DOM::domValueRef()
or
result = jquery()
or
result = externalNode().getAPropertyRead()
or
result = externalNode().getAnInvocation()
or
result = externalNode().(InvokeNode).getCallback(_).getParameter(_)
}
/**
* Gets a data flow node that can be resolved to a function, usually a callback.
*
@@ -192,49 +101,15 @@ class ResolvableCall extends RelevantInvoke {
}
}
/**
* A call site that is believed to call an external function.
*/
class ExternalCall extends RelevantInvoke {
ExternalCall() {
not this instanceof ResolvableCall and // avoid double counting
(
// Call to modelled external library
this = externalNode()
or
// 'require' call or similar
this = moduleImport(_)
or
// Resolved to externs file
exists(this.(InvokeNode).getACallee(1))
or
// Modelled as taint step but isn't from an NPM module, for example, `substring` or `push`.
exists(TaintTracking::AdditionalTaintStep step |
step.step(_, this)
or
step.step(this.getAnArgument(), _)
)
)
}
}
/**
* A call site that could not be resolved.
*/
class UnresolvableCall extends RelevantInvoke {
UnresolvableCall() {
not this instanceof ResolvableCall and
not this instanceof ExternalCall
not this instanceof ResolvableCall
}
}
/**
* A call that is believed to call a function within the same project.
*/
class NonExternalCall extends RelevantInvoke {
NonExternalCall() { not this instanceof ExternalCall }
}
/**
* A function with at least one call site.
*/