Semmle 1.21
Skip to end of metadata
Go to start of metadata

Name: Initialization code not run

Description: Not running initialization code may lead to unexpected behavior.

ID: cpp/initialization-not-run

Kind: problem

Severity: warning

Query: InitialisationNotRun.ql
/**
 * @name Initialization code not run
 * @description Not running initialization code may lead to unexpected behavior.
 * @kind problem
 * @id cpp/initialization-not-run
 * @problem.severity warning
 * @tags reliability
 *       security
 *       external/cwe/cwe-456
 */

import cpp
import semmle.code.cpp.pointsto.CallGraph

predicate global(GlobalVariable v) {
  not exists(v.getInitializer()) and
  not v.getType() instanceof ArrayType and
  not v.getType() instanceof Class and
  v.getAnAccess().isUsedAsLValue()
}

predicate mainCalled(Function f) {
  f.hasGlobalName("main")
  or
  exists(Function caller | mainCalled(caller) and allCalls(caller, f))
}

predicate called(Function f) {
  mainCalled(f)
  or
  exists(FunctionAccess fa | fa.getTarget() = f)
}

from GlobalVariable v
where
  global(v) and
  not exists(VariableAccess lval |
    v.getAnAccess() = lval and
    lval.isUsedAsLValue() and
    called(lval.getEnclosingFunction())
  )
select v, "Initialization code for '" + v.getName() + "' is never run."

The query finds code that initializes a global variable (that is, uses it as an L-value) but is never called from main. Unless there is another entry point that triggers the initialization, the code should be modified so that the variable is initialized. Uninitialized variables may contain any value, as not all compilers generate code that zero-out memory, especially when optimizations are enabled or the compiler is not compliant with the latest language standards.

This check is an approximation, so some results may not be actual defects in the program. It is not possible in general to compute which function is actually called in a virtual call, or a call through a pointer, without running the program with all possible input data.

Recommendation

Examine the code and ensure that the variable is always initialized before it is used.

Example

In the example below, the code that triggers the initialization of g_storage is not run from main. Unless the variable is initialized by another method, the call on line 10 may dereference a null pointer.

GlobalStorage *g_storage;

void init() { //initializes g_storage, but is never run from main
	g_storage = new GlobalStorage();
	...
}

int main(int argc, char *argv[]) {
	... //init not called
	strcpy(g_storage->name, argv[1]); // g_storage is used before init() is called
	...
}

References