Standard Analyses

SemmleCode Professional comes with a wide range of pre-packaged analyses, from architectural properties and metrics, to statement-level checks for likely bugs and violations of best practice.


Possibly Incorrect Lazy Initialization of a Static Field

This query finds code that initializes a non-volatile static field without synchronization. In a multi-threaded program, another thread might start executing before the field is initialized, and will then see an incompletely initialized object.

How to Interpret the Query Results

The query flags every such initialization attempt and also displays the list of generated warnings in the result view.

How to Address the Query Results

The easiest solution is usually to make the surrounding method synchronized.

You could also declare the field volatile and use the double-checked locking pattern. Notice, however, that this can lead to quite subtle problems.

Source Code
import default

/** A comparison (using ==) with null */
class NullEQExpr extends EQExpr {
  NullEQExpr() {
    exists(NullLiteral l | l.getParent() = this)
  }
}

/* Flow analysis to determine sequence of the following operations: Compare static field 
   to null, create new object, store that object in the field. 
   Ignore non reference fields, Strings, java.awt.*, javax.swing.*
   
   Simplified version below searches for the exact source pattern below. */
class LazyStaticFieldInit extends IfStmt {
  LazyStaticFieldInit() {
    exists(Field f, RefType t, FieldAccessInThis access, 
           NullEQExpr nulltest, InitField init | 
           f.hasModifier("static") and
           f.getType() = t and
           not (   t instanceof TypeString
                or t.getPackage().getName().matches("java.awt.%") 
                or t.getPackage().getName().matches("javax.swing.%")) and
          access.getField() = f and
          access.getParent() = nulltest and
          this.getCondition() = nulltest and
          this.getThen() = (ExprStmt)init.getParent() and
          init.getField() = f and
          not this.getEnclosingCallable().hasModifier("synchronized")
    )
  }
}

/** An assignment of a new object to a field in this object */
class InitField extends AssignExpr {
  InitField() {
    this.getDest() instanceof FieldAccessInThis and 
    this.getSource() instanceof ClassInstanceExpr
  }

  Field getField() {
    result = ((FieldAccessInThis)this.getDest()).getField()
  }
}

/** An access of a field in this object */
class FieldAccessInThis extends VarAccess {
  FieldAccessInThis() {
    this.getVariable() instanceof Field and 
    (not this.hasQualifier() or this.getQualifier() instanceof ThisAccess)
  }

  Field getField() {
    result = this.getVariable()
  }

}

from LazyStaticFieldInit i
select i, "Incorrect lazy initialization of static field "
References

Wikipedia article on the Double-Checked Locking Pattern

The "Double-Checked Locking is Broken" Declaration