Files
codeql/javascript/ql/src/Declarations/MissingVarDecl.ql
2020-02-27 09:41:01 +00:00

71 lines
2.2 KiB
Plaintext

/**
* @name Missing variable declaration
* @description If a variable is not declared as a local variable, it becomes a global variable
* by default, which may be unintentional and could lead to unexpected behavior.
* @kind problem
* @problem.severity warning
* @id js/missing-variable-declaration
* @tags reliability
* maintainability
* @precision high
*/
import javascript
/**
* Gets an undeclared global in `f`, that is, a global variable that is accessed in `f`,
* but not declared in the same toplevel as `f`.
*/
GlobalVariable undeclaredGlobalIn(Function f) {
exists(GlobalVarAccess gva | gva = result.getAnAccess() |
gva.getEnclosingFunction() = f and
not result.declaredIn(f.getTopLevel()) and
not exists(Linting::GlobalDeclaration gd | gd.declaresGlobalForAccess(gva))
)
}
/**
* Gets an accidental global in `f`, that is, an undeclared global in `f` that is not
* live at the entry of `f`, meaning that it is always written before being read the
* first time.
*/
GlobalVariable accidentalGlobalIn(Function f) {
result = undeclaredGlobalIn(f) and
exists(BasicBlock startBB | startBB = f.getStartBB() | not startBB.isLiveAtEntry(result))
}
/**
* Gets an accidental global in `f` that is read at least once in reachable code.
*
* This prevents duplication of results between this query and 'Useless assignment
* to global variable'.
*/
GlobalVariable candidateVariable(Function f) {
result = accidentalGlobalIn(f) and
f.getStartBB().getASuccessor*().useAt(_, result, _)
}
/**
* Gets an access to `v` in function `f`.
*/
GlobalVarAccess getAccessIn(GlobalVariable v, Function f) {
result.getEnclosingFunction() = f and
result = v.getAnAccess()
}
/**
* Gets the (lexically) first access to variable `v` in function `f`.
*/
GlobalVarAccess getFirstAccessIn(GlobalVariable v, Function f) {
result =
min(getAccessIn(v, f) as gva
order by
gva.getLocation().getStartLine(), gva.getLocation().getStartColumn()
)
}
from Function f, GlobalVariable gv
where gv = candidateVariable(f)
select getFirstAccessIn(gv, f),
"Variable " + gv.getName() + " is used like a local variable, but is missing a declaration."