mirror of
https://github.com/github/codeql.git
synced 2026-01-27 21:33:03 +01:00
111 lines
2.6 KiB
Plaintext
111 lines
2.6 KiB
Plaintext
/**
|
|
* @name Global variable may be used before initialization
|
|
* @description Using an uninitialized variable may lead to undefined results.
|
|
* @kind problem
|
|
* @id cpp/global-use-before-init
|
|
* @problem.severity warning
|
|
* @tags reliability
|
|
* security
|
|
* external/cwe/cwe-457
|
|
*/
|
|
import cpp
|
|
import semmle.code.cpp.pointsto.CallGraph
|
|
|
|
predicate initFunc(GlobalVariable v, Function f)
|
|
{
|
|
exists(VariableAccess access |
|
|
v.getAnAccess() = access and
|
|
access.isUsedAsLValue() and
|
|
access.getEnclosingFunction() = f)
|
|
}
|
|
|
|
predicate useFunc(GlobalVariable v, Function f)
|
|
{
|
|
exists(VariableAccess access |
|
|
v.getAnAccess() = access and
|
|
access.isRValue() and
|
|
access.getEnclosingFunction() = f)
|
|
and
|
|
not initFunc(v, f)
|
|
}
|
|
|
|
predicate uninitialisedBefore(GlobalVariable v, Function f)
|
|
{
|
|
f.hasQualifiedName("main")
|
|
or
|
|
exists(Call call, Function g |
|
|
uninitialisedBefore(v, g) and
|
|
call.getEnclosingFunction() = g and
|
|
(not functionInitialises(f, v) or locallyUninitialisedAt(v, call)) and
|
|
resolvedCall(call, f))
|
|
}
|
|
|
|
predicate functionInitialises(Function f, GlobalVariable v)
|
|
{
|
|
exists(Call call |
|
|
call.getEnclosingFunction() = f and
|
|
initialisedBy(v, call))
|
|
}
|
|
|
|
// this predicate is restricted to global variables used in the
|
|
// same function as "call"
|
|
predicate locallyUninitialisedAt(GlobalVariable v, Call call)
|
|
{
|
|
functionInitialises(call.getEnclosingFunction(), v) and
|
|
(
|
|
firstCall(call)
|
|
or
|
|
exists(Call mid |
|
|
locallyUninitialisedAt(v, mid) and not initialisedBy(v, mid) and callPair(mid, call))
|
|
)
|
|
}
|
|
|
|
predicate initialisedBy(GlobalVariable v, Call call)
|
|
{
|
|
exists(Function f |
|
|
resolvedCall(call, f) and
|
|
initialises(v, f))
|
|
}
|
|
|
|
predicate initialises(GlobalVariable v, Function f)
|
|
{
|
|
initFunc(v, f)
|
|
or
|
|
exists(Function mid | initialises(v, mid) and allCalls(f, mid))
|
|
}
|
|
|
|
predicate firstCall(Call call)
|
|
{
|
|
beforeCall(call)
|
|
}
|
|
|
|
predicate beforeCall(ControlFlowNode node)
|
|
{
|
|
exists(Function f | f.getBlock() = node)
|
|
or
|
|
exists(ControlFlowNode mid |
|
|
beforeCall(mid) and
|
|
not mid instanceof Call and
|
|
node = mid.getASuccessor())
|
|
}
|
|
|
|
predicate callPair(Call call, Call successor)
|
|
{
|
|
callReaches(call, successor)
|
|
}
|
|
|
|
predicate callReaches(Call call, ControlFlowNode successor)
|
|
{
|
|
call.getASuccessor() = successor
|
|
or
|
|
exists(ControlFlowNode mid |
|
|
callReaches(call, mid) and
|
|
not mid instanceof Call
|
|
and mid.getASuccessor() = successor)
|
|
}
|
|
|
|
from GlobalVariable v, Function f
|
|
where uninitialisedBefore(v, f)
|
|
and useFunc(v, f)
|
|
select f, "The variable '" + v.getName() + " is used in this function but may not be initialized when it is called."
|