mirror of
https://github.com/github/codeql.git
synced 2025-12-24 20:56:33 +01:00
These queries are currently run by default, but don't have their results displayed. Looking through results on LGTM.com, they are either false positives (e.g., `BitwiseSignCheck` which flags many perfectly harmless operations and `CompareIdenticalValues` which mostly flags NaN checks) or harmless results that developers are unlikely to care about (e.g., `EmptyArrayInit` or `MisspelledIdentifier`). With this PR, the only queries that are still run but not displayed are security queries, where different considerations may apply.
94 lines
3.2 KiB
Plaintext
94 lines
3.2 KiB
Plaintext
/**
|
|
* @name Cyclic module import
|
|
* @description If a module indirectly imports itself, some modules involved in the import cycle may end up
|
|
* with partially loaded dependencies. This is error-prone and should be avoided.
|
|
* @kind problem
|
|
* @problem.severity warning
|
|
* @id js/node/cyclic-import
|
|
* @tags reliability
|
|
* maintainability
|
|
* frameworks/node.js
|
|
* @precision low
|
|
*/
|
|
|
|
import javascript
|
|
|
|
/**
|
|
* Gets the shortest suffix of the path of `c1` that differs from the
|
|
* corresponding suffix of `c2`; if that suffix is a proper suffix, it is
|
|
* additionally prefixed with `.../`.
|
|
*/
|
|
string ppDiff(Container c1, Container c2) {
|
|
relatedAncestors(c1, c2) and
|
|
if c1.getBaseName() = c2.getBaseName()
|
|
then result = ppDiff(c1.getParentContainer(), c2.getParentContainer()) + "/" + c1.getBaseName()
|
|
else
|
|
if
|
|
not exists(c1.getParentContainer()) or
|
|
sourceLocationPrefix(c1.getParentContainer().getAbsolutePath())
|
|
then result = "/" + c1.getBaseName()
|
|
else result = ".../" + c1.getBaseName()
|
|
}
|
|
|
|
/**
|
|
* Holds if `c1` and `c2` are related modules (as determined by predicate
|
|
* `relatedModules`), or (transitive) parent folders of such modules.
|
|
*
|
|
* This predicate is used to restrict the domain of `ppDiff`.
|
|
*/
|
|
predicate relatedAncestors(Container c1, Container c2) {
|
|
exists(NodeModule m, NodeModule n | relatedModules(m, n) | c1 = m.getFile() and c2 = n.getFile())
|
|
or
|
|
relatedAncestors(c1.(Folder).getAChildContainer(), c2.(Folder).getAChildContainer())
|
|
}
|
|
|
|
/**
|
|
* Gets a pretty-printed name for `m` that distinguishes it from `other`:
|
|
* this is simply the name of `m` it is different from the name of `other`,
|
|
* or else a suffix of the path of `m` that is different from `other` as
|
|
* computed by `ppDiff`.
|
|
*/
|
|
string pp(NodeModule m, NodeModule other) {
|
|
relatedModules(m, other) and
|
|
if m.getName() = other.getName() and m != other
|
|
then result = ppDiff(m.getFile(), other.getFile())
|
|
else result = m.getName()
|
|
}
|
|
|
|
/**
|
|
* Holds if `m` imports `n` or vice versa.
|
|
*
|
|
* This predicate is used to restrict the domain of `pp`.
|
|
*/
|
|
predicate relatedModules(NodeModule m, NodeModule n) {
|
|
n = m.getAnImportedModule() or m = n.getAnImportedModule()
|
|
}
|
|
|
|
from NodeModule m, Require r, NodeModule imported, string msg, ASTNode linktarget, string linktext
|
|
where
|
|
r = m.getAnImport() and
|
|
imported = r.getImportedModule() and
|
|
if imported = m
|
|
then
|
|
// set linktarget and linktext to dummy values in this case
|
|
msg = "directly imports itself" and linktarget = m and linktext = ""
|
|
else
|
|
// find an import in `imported` that (directly or indirectly) imports `m`
|
|
exists(Require r2, Module imported2 |
|
|
r2 = imported.getAnImport() and imported2 = r2.getImportedModule()
|
|
|
|
|
imported2.getAnImportedModule*() = m and
|
|
msg = "imports module " + pp(imported, m) + ", which in turn $@ it" and
|
|
linktarget = r2 and
|
|
// check whether it is a direct or indirect import
|
|
(
|
|
if imported2 = m
|
|
then linktext = "imports"
|
|
else (
|
|
// only report indirect imports if there is no direct import
|
|
linktext = "indirectly imports" and not imported.getAnImportedModule() = m
|
|
)
|
|
)
|
|
)
|
|
select r, "Module " + pp(m, imported) + " " + msg + ".", linktarget, linktext
|